Vous êtes ici

Trucs de geek : la commande sed

Lorsque vous souhaitez modifier un fichier texte vous aurez surement besoin de recourir à la commande "sed" qui vous permettra des remplacements sur les lignes sélectionnées. Son principe de fonctionnement est simple : la commande reçoit un flux de données, sélectionne des lignes et les traite et les écrit sur la sortie standard (l'écran).

La commande prendra la forme suivant :

$ sed le_fichier.txt -e "les commandes"

Basiquement sed vous permet d'afficher le contenu d'un fichier.

Afficher certaines lignes :

$ sed -n "10,12p" /etc/passwd

N'affiche que les lignes 10 à 12 du fichier.

Pour n'afficher que la première ligne :

$ sed -n "1p" /etc/passwd

On peut aussi filtrer les lignes dans un fichier :

$ sed -n '/linux/p' fichier_entree.txt > fichier_sortie.txt

Ainsi seules les lignes contenant "linux" seront dans le fichier en sortie. C'est l'équivalent d'un grep.

Autre cas : on n'afficher que les lignes 3 à 10 d'un fichier :

$ sed -n "3,10 p" /etc/samba/smb.conf

Pour ne pas afficher les lignes qui sont des commentaires (commençant par un #) :

$ sed /etc/samba/smb.conf -e '/^#.*$/d'

On prend les lignes qui commencent (^) par un (#) et qui se poursuivent pas un nombre quelconque (*) de caractères (.), et on choisit de les détruire (d) du résultat. On peut donc récupérer un version allégée du fichier de configuration.

Continuons par les substitutions dans les lignes. Le premier  exemple permet de substituter  un mot par un autre :

Soit le fichier ".smbcredentials" qui contient les lignes suivantes  :

username=jfd
password=54mlkjhg

Pour modifier le mot de passe on va écrire un script qui va substituer le nouveau mot de passe à l'ancien. Avec sed cela va ressembler à cela :

mdp=$( cat .smbcredentials|grep password|cut -d'=' -f 2)
sed  -i "s/$mdp/nouveau_mot_de_passe/"

L'option "-i" modifie directement le fichier. La première instruction retrouve l'ancien mot de passe. Et sed réalise la changement. Avec sed toutes les lignes sont lues et copiées en sortie mais seule la ligne correspondant au motif est modifiée car elle correspond au motif de recherche.

Autre exemple de substitution :

$ cat /etc/passwd |sed -e "s/:/*/g"

Qui affichera le fichier en question avec des "*" en guise de séparateur de champ.

Il est possible de modifier les séparateurs de champ quand on doit substituer des "/" entre autre. La formule suivante est donc tout à fait correcte :

$ sed -e "s|/root|/home|g" /etc/passwd

Si vous souhaitez que la modification ne tienne pas compte de la case, ajoutez l'option "i". Sit :

$ sed -e "s|/root|/home|gi" /etc/passwd

Si vous ne souhaitez réaliser les substitutions que sur certaines lignes continues :

$ sed -e "5,7 s|/root|/home|gi" /etc/passwd

Pour supprimer des lignes qui ne contiennent qu'un chiffre, on va utiliser une expression rationnelle :

$ cat test.txt | sed "s/^[0-9]\{,4\}//" > V.txt

La signification des caractères spéciaux est la suivante :

  • ^ correspond au début d'une ligne
  • $ correspond à la fin d'une ligne
  • . correspond à n'importe quel caractère unique
  • * correspond à aucune ou plusieurs occurrences du caractère qui précède
  • [ ] correspond à n'importe lequel des caractères cités entre les crochets

Dans l'exemple ci dessus on sélectionne les lignes qui commencent (^) par un à 4 (\{,4\}) chiffres ([0-9]) et qui se comportent rien ensuite ($ indiquant la fin de la ligne). On substitue (s) à ces chiffres rien (//).

Autre exemple avec l'option "d". Dans un fichier de sous titre je veux supprimer les lignes qui commencent un heure au format "00:00:00". Je fais donc :

$ cat V.srt | sed -e '/^[0-9]\{2\}:.*$/d'> resultat.srt

Je ne copie pas en sortie (d) les lignes qui commencent (^) par deux (\{2\}) chiffres ([0-9]) suivi d'un ":" et d'un nombre quelconque de caractères.

Autre utilisation de l'option "d", ne recopier en sortie un fichier qu'à partir de la 10ème ligne :

$ sed "1,10d" /etc/passwd

N'affiche que les lignes commençant par "ava".

$ sed /etc/passwd -n -e '/^ava/p'

L'option "-n" permet de n'afficher que les lignes sélectionnées. L'option "-p" demande l'affichage sans traitement

Pour supprimer les lignes vides dans un fichier :

$ cat mon_fichier.txt |sed -e '/^$/d'

On n'affiche pas (d) les lignes qui commencent et qui finissent par rien.

Cela permet aussi d'ignorer des lignes dans un fichier :

$ sed '20,35d' myfile.txt

Affiche le fichier en question sauf les lignes 20 à 35.

Si les lignes ne sont pas consécutives il faut recourir à l'opérateur "-e" :

$ sed -n -e '5,7p' -e '10,13p' myfile.txt

Commenter une ligne qui contient une séquance particulière (on pourrait aussi la supprimer) :

$ sed -e 's/.*sequence.*/#$/g' fichier_entree.txt > fichier_sortie.txt

Ce qui est intéressant est la suite ".*" qui s'interprête comme un caractère quelconque répété un nombre de fois quelconque.

Pour supprimer une ligne :

$ sed test.txt -e "/.*JF.*/d" > test2.txt

el les lignes comprenant "JF" seront supprimées en sortie.

On peut ajouter une ligne aprés une ligne repérée par son contenu :

$ sed test.txt -e "/.*JF.*/a LUCIE" > test2.txt

On va ajouter le prénom "LUCIE" aprés la ligne qui contient "JF".

Il est possible de ne remplacer que certaines occurrences trouvées. Si votre fichier contient la ligne à modifier suivante :

linux is great os. unix is opensource. unix is free os.

Si vous voulez changer 'unix" en linux dans la seconde phrase vous ne pouvez pas utiliser le commutateur "g" en faisant "s/unix/linux/g" car cela changerait les deux occurrences 'unix". Il faut donc faire :

$ sed 's/unix/linux/2' mon_fichier.txt

produira la ligne suivante :

unix is great os. linux is opensource. unix is free os.

Il est possible aussi de ne réaliser une substitution qu'à partir d'une certaine occurrence :

$ sed 's/unix/linux/3g' mon_fichier.txt

Ne commence la substitution qu'à partir de la 3ème occurrence. On obtient donc :

unix is great os. unix is opensource. linux is free os.

Fait le 04/03/2016

 

Tags: 

Utilisateurs en ligne

Il y a actuellement 0 utilisateur connecté.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer