Ce billet est largement inspiré de USEFUL ONE-LINE SCRIPTS FOR SED (Unix stream editor) écrit en 2005.
Je suis tombĂ© par hasard sur cette compilation dâexemples pour sed que je trouve trĂšs intĂ©ressante, elle est cependant assez ancienne, je vous propose une adaptation libre et modernisĂ©e.
Ce document a Ă©tĂ© traduit, mais la version française nâĂ©tait pas Ă jour, je me suis appuyĂ© sur les versions anglaise et française.
Lâarticle de base sĂ©pare diffĂ©rentes version de la commande sed, notĂ© que sous les Linux modernes, vous aurez trĂšs probablement la version GNU qui est la plus complĂšte.
Attention, cependant sur les Linux embarqués, vous aurez probablement la version BusyBox. à ce jour LibreElec propose la version BusyBox v1.32.1 (2022-03-05 22:56:19 CET) multi-call binary.
Certains exemples sont « overkill », il nây a pas dâintĂ©rĂȘt de remplacer la commande tac par une Ă©criture sed, mais cela peut donner des idĂ©es pour traitement spĂ©cifique.
sed est un Ă©diteur de flux (« fichier ») permettant de filtrer et de transformer un texte. sed est Ă©tonnement puissant ; comme la plupart des commandes Unix, il est capable de traiter lâentrĂ©e standard, comme un fichier.
Ă noter, en particulier, que lâoption -i
, demande Ă sed dâeffectuer les modifications sur les fichiers sur place (« in place ») ; cela permet de modifier de rĂ©Ă©crire un fichier. Notez que lâoption -i
devient ineffective si sed agit sur lâentrĂ©e standard.
Gestion des lignes (principalement des lignes vides)
-
Traitement sur les lignes
- Ajoute une ligne vide aprÚs chaque ligne :
sed 'G'
- Ajoute deux lignes vides aprÚs chaque ligne :
sed 'G;G'
- Ajoute une ligne vide lorsquâil nây en a pas :
Plus précisément : on supprime toutes les lignes vides, puis on ajoute une ligne vide aprÚs chaque ligne.
sed '/^$/d;G'
- Efface toutes les lignes paires :
Efface les lignes, quâelles soient vides ou non.
sed 'n;d'
- Insérer une ligne vide au-dessus de chaque ligne qui contient « regex » :
sed '/regex/{x;p;x;}'
- InsĂ©rer une ligne vide sous chaque ligne qui contient lâexpression rĂ©guliĂšre « regex » :
sed '/regex/G'
- Insérer une ligne vide au-dessus et au-dessous de chaque ligne qui contient « regex » :
sed '/regex/{x;p;x;G;}'
Numérotation
-
Numérotation des lignes
- Numéroter chaque ligne du fichier (appuyé simplement à gauche) :
Lâutilisation dâune tabulation au lieu dâun espace prĂ©servera les marges.
sed '=' nomdefichier | sed 'N;s/\n/\t/'
- NumĂ©roter chaque ligne dâun fichier (numĂ©ro Ă gauche, appuyĂ© Ă droite) :
sed '=' nomdefichier | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
- NumĂ©roter chaque ligne dâun fichier, mais nâafficher le numĂ©ro de ligne que si la ligne nâest pas vide :
sed '/./=' nomdefichier | sed '/./N; s/\n/ /'
- Compter les lignes (Ă©mulation de
wc -l
)Â :
sed -n '$='
Conversion et substitution de texte
-
Conversion et substitution
- Environnement UNIX : Conversion des retours de chariot (CR/LF) au format Unix :
sed 's/.$//' # assume que toutes les lignes se terminent avec CR/LF sed 's/^M$//' # sous bash/tcsh, utiliser CTRL+V puis CTRL+M sed 's/\x0D$//' # fonctionne sous ssed, gsed 3.02.80 ou plus récent
- Environnement UNIXÂ : Conversion des retours de chariot UNIX (LF) au format DOSÂ :
sed "s/$/`echo -e \\\r`/" # ligne de commande sous ksh sed 's/$'"/`echo \\\r`/" # ligne de commande sous bash sed "s/$/`echo \\\r`/" # ligne de commande sous zsh sed 's/$/\r/' # gsed 3.02.80 ou plus récent
- Environnement DOSÂ : Conversion des retours de chariot Unix (LF) au format DOSÂ :
sed "s/$//" # méthode 1 sed -n "p" # méthode 2
- Environnement DOS : convertir les retours de chariot DOS (CR/LF) au format Unix :
sed "s/\r//" infile >outfile # UnxUtils sed v4.0.7 ou plus récent tr -d \r <infile >outfile # GNU tr version 1.22 ou plus récent
- Ăliminer tout espace blanc (espaces, tabulations) Ă la gauche de chaque ligne, et appuyer le rĂ©sultat Ă la marge gauche :
sed 's/^[ \t]*//' sed 's/^[[:blank:]]*//'
- Ăliminer tout espace blanc (espaces, tabulations) Ă la fin de chaque ligne :
sed 's/[ \t]*$//' sed 's/[[:blank:]]*$//'
- Ăliminer tout espace blanc aux deux bouts de chaque ligne (« trim ») :
sed 's/^[ \t]*//;s/[ \t]*$//' sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
- Insérer 4 espaces au début de chaque ligne (décalage de page vers la droite) :
sed 's/^/ /'
- Aligner tout le texte à la droite sur la 79e colonne :
sed -e ':a' -e 's/^.\{1,78\}$/ &/;ta' # mettre Ă 78 plus un espace
- Centrer tout le texte sur le centre de la 79e colonne :
Dans la premiÚre méthode, tout espace au début de la ligne est significatif, et des espaces sont ajoutés à la fin de la ligne.
Dans la seconde mĂ©thode, les espaces prĂ©cĂ©dant les lignes sont ignorĂ©s pendant le processus de centrage, et aucun espace nâest ajoutĂ© Ă la fin des lignes.sed -e ':a' -e 's/^.\{1,77\}$/ & /;ta' # mĂ©thode 1 sed -e ':a' -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/' # mĂ©thode 2
- Substituer (trouver et remplacer) « foo » avec « bar » sur chaque ligne :
sed 's/foo/bar/' # replacer seulement la premiĂšre instance de la ligne sed 's/foo/bar/4' # replacer seulement la quatriĂšme instance de la ligne sed 's/foo/bar/g' # replacer toutes les instances de la ligne sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # replacer lâavant-dernier cas sed 's/\(.*\)foo/\1bar/' # replacer seulement le dernier cas
- Substituer « foo » par « bar » SEULEMENT pour les lignes contenant « baz » :
sed '/baz/s/foo/bar/g'
- Substituer « foo » par « bar » a lâexception des lignes contenant « baz » :
sed '/baz/!s/foo/bar/g'
- Substituer « scarlet » ou « ruby » ou « puce » par « red » :
sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g' # la plupart des seds gsed 's/scarlet\|ruby\|puce/red/g' # GNU sed seulement
- Inverser lâordre des lignes (Ă©mulation de tac)Â :
PrĂ©fĂ©rez lâusage de tac Ă ce code illisible, sauf si vous utiliser ce code comme base pour un traitement particulier.
sed '1!G;h;$!d' # méthode 1 sed -n '1!G;h;$p' # méthode 2
- Inverser lâordre de chaque caractĂšre sur une ligne (Ă©mulation de rev)Â :
PrĂ©fĂ©rez lâusage de rev Ă ce code illisible, sauf si vous utiliser ce code comme base pour un traitement particulier.
sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
- Joindre des paires de lignes ensemble cĂŽte-Ă -cĂŽte (Ă©mulation de paste)Â :
sed '$!N;s/\n/ /'
- Si une ligne se termine par une barre oblique inversée, joindre la ligne suivante à la présente :
sed -e ':a' -e '/\\$/N; s/\\\n//; ta'
- Si une ligne dĂ©bute par le symbole Ă©galitĂ©, lâajouter Ă la prĂ©cĂ©dente et remplacer le symbole
=
par un espace simple :
sed -e ':a' -e '$!N;s/\n=/ /;ta' -e 'P;D'
- Insérer des virgules aux chaßnes numériques, changeant
1234567
en1,234,567
(format US)Â :
gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta' # GNU sed sed -e ':a' -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' # autres seds
- Décimaux et signes négatifs (GNU sed) :
gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'
- Ajouter une ligne blanche Ă chaque cinq lignes (aprĂšs lignes 5, 10, 15, 20, etc.)Â :
gsed '0~5G' # GNU sed seulement sed 'n;n;n;n;G;' # autres seds
Ăffassement sĂ©lectif de certaines lignes
-
Ăcrasement sĂ©lectif de lignes
- Imprime tout le fichier sauf la section coïncidant avec deux expressions réguliÚres :
sed '/Iowa/,/Montana/d'
- Ălimine les lignes consĂ©cutives identiques dâun fichier (Ă©mulation uniq) :
La premiĂšre ligne dâun ensemble de lignes identiques consĂ©cutives est retenue, les autres Ă©liminĂ©es.
sed '$!N; /^\(.*\)\n\1$/!P; D'
- Ălimine les lignes en duplicata, non-consĂ©cutives, dâun fichier :
Prenez garde de ne pas déborder les limites de la mémoire tampon sinon veuillez utiliser le GNU sed.
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
- Ăliminer toutes les lignes sauf celles en duplicata (Ă©mulation
uniq -d
)Â :
sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'
- Ăliminer les dix premiĂšres lignes dâun fichier :
sed '1,10d'
- Ăcraser la derniĂšre ligne dâun fichier :
sed '$d'
- Ăcraser les deux derniĂšres lignes dâun fichier :
sed 'N;$!P;$!D;$d'
- Ăcraser les dix derniĂšres lignes dâun fichier :
sed -e ':a' -e '$d;N;2,10ba' -e 'P;D' # méthode 1 sed -n -e ':a' -e '1,10!{P;N;D;};N;ba' # méthode 2
- Ăcraser chaque huitiĂšme ligne :
gsed '0~8d' # GNU sed seulement sed 'n;n;n;n;n;n;n;d;' # autres seds
- Ăcraser les lignes coĂŻncidant avec un patron :
sed '/patron/d'
- Ăcraser toutes les lignes vides dâun fichier (Ă©mulation
grep '.'
)Â :
sed '/^$/d' # méthode 1 sed '/./!d' # méthode 2
- Ăcraser toutes les lignes vides consĂ©cutives (sauf la premiĂšre) :
Ăcrase aussi toutes les lignes vides du dĂ©but et de la fin dâun fichier (Ă©mulation
cat -s
).sed '/./,/^$/!d' # méthode 1, retient 0 ligne vide au début, 1 à la fin sed '/^$/N;/\n$/D' # méthode 2, permet 1 ligne vide au début, 0 à la fin
- Ăcraser toutes lignes vides CONSĂCUTIVES d'un fichier, sauf les deux premiĂšres :
sed '/^$/N;/\n$/N;//D'
- Ăcraser toutes les lignes vides au dĂ©but dâun fichier :
sed '/./,$!d'
- Ăcraser toutes les lignes vides de la fin dâun fichier :
sed -e ':a' -e '/^\n*$/{$d;N;ba' -e '}' # fonctionne sur tous les seds sed -e ':a' -e '/^\n*$/N;/\n$/ba' # ibid, sauf pour gsed 3.02.*
- Ăcrase la derniĂšre ligne de chaque paragraphe :
sed -n '/^$/{p;h;};/./{x;/./p;}'
Applications spécifiques
-
Applications spécifiques
- Ăliminer les sur-frappes nerf (char, retour) des pages man :
La commande echo peut nécessiter le modificateur
-e
si vous utilisez Unix System V ou du shell bash.sed "s/.`echo \\\b`//g" # double guillemets requis dans lâenvironnement Unix sed 's/.^H//g' # sous bash/tcsh, utiliser CTRL+V puis CTRL+H sed 's/.\x08//g' # expression hexadĂ©cimale pour sed 1.5, GNU sed, ssed
- Obtenir lâentĂȘte des messages Usenet/courriel :
sed '/^$/q' # Ă©limine tout ce qui suit la premiĂšre ligne vide
- Obtenir le corps des messages Usenet/courriel :
sed '1,/^$/d' # élimine tout ce qui précÚde la premiÚre ligne vide
- Obtenir lâentĂȘte Sujet, mais Ă©limine la portion initiale
Subject:
 :
sed '/^Suject: */!d; s///;q'
- Obtenir lâadresse de retour dans lâentĂȘte (Fichier *.eml)Â :
sed '/^Reply-To:/q; /^From:/h; /./d;g;q'
- Parcourir et isoler lâadresse proprement dite :
Extirpe lâadresse courriel par elle-mĂȘme, du script prĂ©cĂ©dent.
sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'
- Ajouter un crochet et espace Ă chaque ligne (citer un message)Â :
sed 's/^/> /'
** Ăcraser le crochet et espace prĂ©cĂ©dant chaque ligne (enlever la citation du message) :
sed 's/^> //'
- Ăcraser la plupart des Ă©tiquettes HTML (sâaccommode des Ă©tiquettes multi-lignes)
sed -e ':a' -e 's/<[^>]*>//g;/</N;//ba'
- Extraire les parties uuencodĂ©es binaires, Ă©liminant les entĂȘtes superflus, de façon Ă garder seulement la partie uuencodĂ©e.
Les fichiers doivent ĂȘtre passĂ©s Ă sed dans le bon ordre.
La version 1 peut ĂȘtre passĂ©e depuis la ligne de commande ;
la version 2 peut faire partie dâun script de shell Unix (ModifiĂ©e par un script).sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode # version 1 sed '/^end/,/^begin/d' "$@" | uudecode # version 2
- Triage des paragraphes dâun fichier par ordre alphabĂ©tique.
Les paragraphes sont sĂ©parĂ©s pour des lignes vides. GNU sed utilise \v comme tabulation verticale, ou nâimporte lequel caractĂšre unique peut servir.
sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g' gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'
- Compresser en zip chaque fichier « .TXT » individuellement, écrasant le fichier source et assignant le nom du fichier compressé « .ZIP ».
Au nom de base du fichier source .TXT (sous DOS: le modificateur "dir /b" retourne les noms de base des fichiers tout en majuscules)
echo @echo off >zipup.bat dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat
Usage typique
-
Usage typique de sed
sed accepte une ou plusieurs commandes et les applique toutes, de façon sĂ©quentielle, Ă chacune des lignes dâentrĂ©e.
Une fois que toutes les commandes furent exĂ©cutĂ©es Ă la premiĂšre ligne dâentrĂ©e, cette ligne est envoyĂ©e vers la sortie, une deuxiĂšme ligne est lue comme nouvelle entrĂ©e, et le cycle se rĂ©pĂšte.
Les exemples prĂ©cĂ©dents prĂ©sument que lâentrĂ©e provient de lâentrĂ©e standard (ex. la console, normalement ce serait lâentrĂ©e dans un pipeline|
). Un ou plusieurs noms de fichiers peuvent ĂȘtre ajoutĂ©s Ă la ligne de commande si lâentrĂ©e ne provient pas de lâentrĂ©e standard. La sortie est passĂ©e Ă la
sortie standard (stdout ou lâĂ©cran-tĂ©moin).Donc :
cat nomdefichier | sed '10q' # utilise entrĂ©e pipeline sed '10q' nomdefichier # mĂȘme chose, en moins du cat inutile sed '10q' nomdefichier > nouveaufichier # redirige la sortie vers le disque
Pour des renseignements additionnels sur la syntaxe, incluant comment fournir les instructions sed Ă partir dâun fichier au lieu de la ligne de commande, veuillez consulter le livre "SED & AWK, 2nd Edition," par Dale Dougherty et Arnold Robbins (O'Reilly, 1997; www.ora.com), "UNIX Text Processing," par Dale Dougherty and Tim O'Reilly (Hayden Books, 1987) ou les tutoriels par Mike Arst distribuĂ©s dans U-SEDIT2.ZIP (plusieurs sites).
Afin dâexploiter la pleine puissance de sed, lâusager doit comprendre les « expressions rĂ©guliĂšres ». Ă cette fin, consultez "Mastering Regular Expressions" par Jeffrey Friedl (O'Reilly, 1997).
Le manuel UNIX (man) contient des pages qui pourraient ĂȘtre utiles (
man sed
,man regexp
, ou la sous-section sur les expressions réguliÚres (man ed
), quoique les pages man sont notoires pour leurs difficultĂ©s. Elles ne furent pas rĂ©digĂ©es pour enseigner lâusage de sed ou des expressions rĂ©guliĂšres, mais comme texte de rĂ©fĂ©rence pour ceux qui connaissent dĂ©jĂ ces outils.SYNTAXE DE CITATION:
Les exemples précédents utilisent les guillemets simples ('...') au lieu des guillemets doubles ("...") pour encadrer ou citer les commandes d'édition, puisque sed est
typiquement utilisé sur les systÚmes d'exploitation UNIX.Les guillemets simples préviennent le shell UNIX d'interpréter les symbole dollar ($) ainsi que les guillemets renversés (
...
) qui seraient interprétés par le shell s'ils seraient encadrés ou cités par les guillemets doubles.
Les usagers du shell "csh" et dĂ©rivĂ©s doivent aussi citer le point d'exclamation avec l'oblique arriĂšre (!) si l'on veut que les exemples ci-haut fonctionnent, mĂȘme avec Ă l'intĂ©rieur de guillemets simples. Les versions de sed Ă©crites pour DOS invariablement requiĂšrent des guillemets doubles ("...") au lieu des guillemets simples utilisĂ©s pour citer les commandes d'Ă©dition sed.
Lâusage de '\t' dans les scripts « sed »
-
Les tabulations
Afin de clarifier la documentation, nous avons utilisĂ© lâexpression '\t' pour indiquer le caractĂšre de tabulation (0x09) dans les scripts.
Cependant, la plupart des versions de sed ne reconnaissent pas l'abréviation '\t', donc, lorsque vous écrirez ces directives à l'invite de commande, vous devrez enfoncer la clef TAB au lieu de l'abréviation. '\t' est supporté comme métacharactÚre d'expression réguliÚre dans awk, perl, et HHsed, sedmod, et GNU sed v3.02.80.
Versions de sed
Les versions de sed diffÚrent entre elles, et de légers écarts de syntaxe se présentent.
En particulier, la plupart ne reconnaissent pas l'usage d'Ă©tiquettes (:nom
) ou ne permettent pas les instructions de branchement (b,t) à l'intérieur des commandes d'édition, sauf à la fin de ces commandes.
Nous avons donc utilisé une syntaxe qui serait portable à la majorité des usagers de divers sed, bien que les versions les plus populaires du GNU sed permettent une syntaxe plus élaborée.
Lorsque les lecteurs verront une longue chaĂźne de commande telle celle-ci:
sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
ils seront réjouis de savoir que GNU sed leur permettra de réduire le tout en ceci:
sed '/AAA/b;/BBB/b;/CCC/b;d' # ou bien encore en ceci:
sed '/AAA\|BBB\|CCC/b;d'
En plus, se rappeler que bien que certaines versions de sed acceptent une commande telle "/one/ s/RE1/RE2/", d'autres ne permettent pas ceci:
"/one/! s/RE1/RE2/", qui contient un espace avant le 's'. Ăviter d'enter l'espace lorsque vous entrez la commande.
Optimisation pour vitesse d'exécution
Lorsque vous avez besoin de vitesse pour l'exĂ©cution de vos scripts (si vos fichiers d'entrĂ©e sont volumineux, ou un processeur lent ou un disque dur lent) la substitution sera plus rapide si vous faites un recherche pour la chaĂźne Ă ĂȘtre changĂ©e avant de faire la substitution "s/.../.../".
Voir:
sed 's/foo/bar/g' nomdefichier # commande normale de substitution
sed '/foo/ s/foo/bar/g' nomdefichier # exécution plus rapide
sed '/foo/ s//bar/g' nomdefichier # raccourci de syntaxe
Si vous devez altérer ou écraser seulement une section d'un fichier et que vous voulez seulement une sortie pour une premiÚre partie d'un fichier quelconque, la commande "quit" (q) dans le script réduira considérablement le temps d'exécution pour de gros fichiers.
Donc:
sed -n '45,50p' nomdefichier # imprimez les lignes nos. 45-50 d'un fichier
sed -n '51q;45,50p' nomdefichier # ibid, mais bien plus vite
Références et liens
- Liens vers le document de base de ce billet :
- Version récente de document en anglais
- Version en français
- Adresse alternative de la version anglaise
- Adresse alternative de la version française
- Autres liens :
- Critique du document en français,
- Sed - An Introduction and Tutorial by Bruce Barnett, une documentation assez complĂšte de sed,
- La documentation de GNU sed en anglais,
- Présentation de BusyBox sur Wikipedia.
኿