cClaude.rocks ☕ Le blog

[Nouvelles technologies, sciences et coups de gueule…]

Menu

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 en 1,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

኿


â„č 2006 - 2024 | 🏠 Accueil du domaine | 🏡 Accueil du blog