Sed

Substitution

  • Substituer “foo” par “bar” à chaque ligne
    • Seulement la 1ère occurrence
      • sed 's/foo/bar/'
    • Seulement la 3ème occurrence
      • sed 's/foo/bar/3'
    • Toutes les occurrences
      • sed 's/foo/bar/g'
    • Seulement l’avant dernière occurrence
      • sed 's/\(.*\)foo\(.*foo\)/\1bar\2/'
    • Seulement la dernière occurrence
      • sed 's/\(.*\)foo/\1bar/'
    • Substituer “foo” par “bar” seulement les lignes contenant “plop
      • sed '/plop/ s/foo/bar/g'
    • Substituer “foo” par “bar” excepté les lignes contenant “plop
      • sed '/plop/! s/foo/bar/g'
    • Substituer “Foo” ou “foo” par “bar” à chaque ligne
      • sed 's/[Ff]oo/bar/g'
    • Substituer “bleu” ou “blanc” ou “rouge” par “vert
      • sed 's/bleu\|blanc\|rouge/vert/g'

Affichage

  • La 1ère ligne (head -1)
    • sed q
  • Les 5 premières lignes (head -5)
    • sed '5q'
    • sed '1,5!d'
  • La dernière ligne (tail -1)
    • sed -n '$p'
    • sed '$!d"
  • Les 5 dernières lignes (tail -5)
    • sed -e :a -e '$q;N;6,$D;ba'
  • Les 2 dernières lignes (tail -2)
    • sed '$!N;$!D'
  • Seulement les lignes matchant un motif ou une expression régulière
    • sed -n '/motif/p'
    • sed '/regexp/!d'
  • Seulement les lignes ne matchant pas un motif ou une expression régulière
    • sed -n '/motif/!p'
    • sed '/regexp/d'
  • La ligne précédent un motif ou une expression régulière
    • sed -n '/motif/{g;1!p;};h'
  • La ligne suivant un motif ou une expression régulière
    • sed -n '/regexp/{n;p;}'

Suppression

Espace et tabulation

  • Éliminer les espaces et tabulations
    • En début de ligne
      • sed 's/^[ \t]*//
      • sed 's/^\s*//'	# Utilisation du paramètre "\s"
    • En fin de ligne
      • sed 's/[ \t]*$//'
    • En début et fin de ligne
      • sed 's/^[ \t]*//;s/[ \t]*$//'

Ligne vide

  • Éliminer les lignes vides
    • Toutes les lignes vides
      • sed '/^$/d'
      • sed '/./!d'
    • Uniquement celles d’en tête
      • sed '/./,$!d'
      • sed -nr '/./,$s/(.*)/\1/p'	# merci Adrien
    • Uniquement celles de fin
      • sed -e :a -e '/^\n*$/ {$d;N;ba' -e '}'

Intervalle régulier

  • Éliminer une ligne à intervalles réguliers
    • Toutes les lignes paires
      • sed '1~2d'
    • Toutes les lignes impaires
      • sed '2~2d'
    • Toutes les n lignes à partir de la ligne n
      • sed '3~2d'	# Toutes les 2 lignes à partir de la ligne 3

Divers

Joindre des lignes

  • Joindre les lignes 2 par 2
    • sed '$!N;s/\n//'
  • Joindre les lignes 3 par 3
    • sed '$!N;s/\n//;$!N;s/\n//;'
  • Si une ligne se termine par un backslash (\), ajouter la ligne suivante et remplacer la fin de ligne (\n) par un espace
    • sed -e :a -e '/\\$/N; s/\\\n/ /; ta'
  • Si une ligne commence par un signe égale (=), ajouter-là à la ligne précédente et remplacer le signe égale (=) par un espace
    • sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

Affichage insensible à la casse

(Afficher uniquement les lignes correspondant à un motif donné avec insensibilité à la casse)

Cette astuce fait suite à cette discussion sur le forum Linux/Unix

La commande “sed” possède bien un “flag” – voir Sed – Introduction à SED – Part I – permettant de mettre en correspondance un motif sans tenir compte de la casse, mais ce flag ne s’applique qu’à la seule commande de substitution (commande s) malheureusement.

Voilà donc une astuce permettant de se servir de ce flag pour afficher (ou au contraire ne pas afficher) des lignes correspondant à un motif donné sans tenir compte de sa casse.
Il suffit pour cela d’employer la commande de substitution “s” combinée au métacaractère “& et bien sur du flag “I“.

Exemple pour n’afficher que les lignes contenant le terme “motif” (ou Motif, MOTIF, mOtIf, MoTiF, etc)

  • sed -n 's/motif/&/Ip' fichier

Supprimer une (ou plusieurs) ligne(s) d’un fichier

Syntaxe

sed '{[/]<n>|<chaîne>|<regex>[/]}d' <nom_fichier> sed '{[/]<adr1>[,<adr2>][/]d' <nom_fichier>
  • /…/ = délimiteurs
  • n = le numéro de ligne
  • chaîne = la chaîne contenue dans la ligne
  • regex = l’expression régulière correspondant au motif recherché
  • adr = l’adresse d’une ligne (numéro ou motif)
  • d = delete (effacer)

Exemples

Suppression de la 3ème ligne

sed '3d' mon_fichier.txt

Suppression de la ligne contenant la chaîne “awk”

sed '/awk/d' mon_fichier.txt

Suppression de la dernière ligne

sed '$d' mon_fichier.txt

Suppression de toutes les lignes vides

sed '/^$/d' mon_fichier.txt sed '/./!d' mon_fichier.txt

Suppression de la ligne “matchée” par une expression régulière
(ici on élimine celle contenant des caractères numérique (au moins 1 chiffre) situés en fin de ligne)

sed '/[0-9/][0-9]*$/d' mon_fichier.txt

Suppression de l’intervalle compris entre les lignes 7 et 9

sed '7,9d' mon_fichier.txt

La même chose mais en remplaçant l’adresse par des “motifs”

sed '/-Début/,/-Fin/d' mon_fichier.txt

Note

Les exemples précédents ne font que modifier l’affichage du fichier (sortie standard 1 = l’écran).
Pour des modifications permanentes, pour les anciennes versions (< 4) utiliser un fichier temporaire, pour GNU sed utiliser le paramètre “-i[suffixe]” (–in-place[=suffixe]), comme dans l’exemple suivant :

sed -i".bak" '3d' mon_fichier.txt

qui aura pour effet, de ne produire aucun affichage sur la sortie standard, de modifier le fichier original “mon_fichier.txt” en supprimant la 3ème ligne et de créer un fichier de sauvegarde nommé “mon_fichier.txt.bak“.

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.

 

Sources

Sources

Sources

Laisser un commentaire