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'
-
- Seulement la 1ère occurrence
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]*$//'
-
- En début de ligne
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 '}'
-
- Toutes les lignes vides
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
-
- Toutes les lignes paires
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.