Ce document est une introduction à la pratique et à l'utilisation de l'éditeur de flux "SED", qui essaie de couvrir certaines fonctionnalités assez méconnues, pour ne pas dire "quasi inconnues", qui font de "SED" un outil indispensable dans la boîte à outils de tout Linuxien désireux de se rompre aux maniements et aux arcanes du traitement de fichiers via une console et un shell.
$ echo "azerty azerty azerty" | sed 's/az/qw/' qwerty azerty azerty
$ echo "azerty azerty azerty" | sed 's/az/qw/2' azerty qwerty azerty
$ echo "azerty azerty azerty" | sed 's/az/qw/3' azerty azerty qwerty
$ echo "azerty azerty azerty" | sed 's/az/qw/g' qwerty qwerty qwerty
sed ' :s # étiquette N # on ajoute la ligne suivante s/\n/ / # on substitue les fins de lignes par un espace b s # on se branche à l'étiquette 'Sur une ligne :
sed ':s;N;s/\n/ /;bs'
sed -n '/foo/,/bar/{//d;p}' fichier
sed -n '/Mandriva/,/RedHat/{//d;p}' adresses.txt
$ echo "azerty azerty azerty" | sed 's/a.*z/qw/' qwerty $ echo "azerty azerty azerty" | sed 's/a[^a]*z/qw/' qwerty azerty azerty
$ echo -e "111\n222\n333\n444" | sed '/222/{n; s/3/4/2}'
111
222
343
444
$ echo -e "111\n222\n333\n444" | sed -n '/222/{n; s/3/4/2p}'
343
$ echo -e "AAA\nBBB\nCCC\nDDD" | sed '/BBB/ {n;s/C/Z/2}'
AAA
BBB
CZC
DDD
$ echo -e "AAA\nBBB\nCCC\nDDD" | sedsed -i '/BBB/ {n;s/C/Z/2}'
/BBB/ { # On sélectionne la ligne avec ce motif
n # On place la ligne suivante dans l'espace de travail
s/C/Z/2 # On remplace le 2nd C par un Z
}
sed '
6 { # sélection de la ligne
h # copie dans la mémoire annexe
N # ajout dans la mémoire principale de la ligne suivante
G # ajout du contenu de la mémoire annexe à la mémoire principale
#+ la mémoire principale contenant à ce moment là :
#++ Ligne n° 6\nLigne n°7\nLigne n° 6\n
D # effacement jusqu'au 1er caractère de fin de ligne (\n)
}
'
sed '6 {h;N;G;D}'
#! /bin/sed -f
1 h # chargement 1ère ligne mémoire secondaire
1 d # effacement 1ère ligne
5 { # sélectionner sur la ligne 5
G # ajouter le contenu de la mémoire secondaire à la mémoire principale
N # ajouter la ligne suivante (la 6)
s/\n/ /g # substituer tous les sauts de ligne (\n) par un espace
}
sed -n '1 h; 1 d; 5 { G; N; s/\n/ /g};P' fich.txt
sed '
/^#\|^$/! { # Exclure les lignes débutant par un dièse et les lignes vides
/#/ { # Si la ligne contient un dièse
h # La copier dans l'espace annexe. L'original est encore dans l'espace de travail
s/.*\(#.*\)/\1/ # Ne conserver que ce qui se trouve après le dièse (dièse compris)
x # Échanger l'espace de travail avec l'espace annexe
s/\(.*\)#.*/\1/ # Ne conserver que ce qui se trouve avant le dièse
x # Échanger l'espace de travail avec l'espace annexe
G # Ajouter le contenu de l'espace annexe à l'espace de travail
}
}
' prog.sed
sed '/^#\|^$/!{/#/{h; s/.*\(#.*\)/\1/;x;s/\(.*\)#.*/\1/;x;G;}};' prog.sed
sed -n '
/^$/ {
n
/^#/p
}
' fich2.txt
sed -n '/^$/{n;/^#/p}' fich2.txt
#!/bin/sh # Émulation de grep -A3 -B5 "motif" fichier # Largement inspiré du script grep4.sh # sur le site : http://www.grymoire.com/Unix/Sed.html#uh-56 case "$#" in 1) ;; *) echo "Usage: $0 \motif\" < fichier";exit;; esac; sed -n ' '/$1/' !{ # Motif non satisfait - ajouter la ligne dans la mémoire annexe H # Remettez-le dans la mémoire principale (espace de travail) x # Ne conserver que 3 lignes dans le tampon # 2 lignes correspondent à .*\n.* # 3 lignes à .*\n.*\n.* # On efface les lignes excédentaires s/^.*\n\(.*\n.*\n.*\)$/\1/ # Mettre les 3 lignes (au plus) dans la mémoire annexe à nouveau x } '/$1/' { # Le motif est satisfait - Ajouter le contenu de la mémoire principale # à la mémoire secondaire H # Prendre la ligne suivante (n) et ajouter les 4 autres (N) n;N;N;N;N # Ajouter le tout à la mémoire annexe H # Échanger le tout avec la mémoire principale x # Afficher les lignes p }'
sed -n '/ERROR/! {H;x;s/^.*\n\(.*\n.*\n.*\)$/\1/;x;}; /ERROR/ {H;n;N;N;N;N;H;x;p}'
#! /bin/bash
sed -n ' # affichage sur demande uniquement
/indice7/! { # motif absent
x # on place la ligne dans la mémoire annexe (en fait on échange le contenu)
d # on efface l'espace de travail
}
/indice7/ { # motif présent
x # on l'échange avec le contenu de la mémoire annexe qui contient la ligne précédente
p # on l'affiche
x # on échange à nouveau la contenu des 2 mémoires
p # on affiche la ligne contenant le motif
n # on charge la ligne suivante
p # on l'affiche
x # on la replace dans la mémoire annexe
}
' fich3.txt
sed -n '/indice7/! {x;d;}; /indice7/{x;p;x;p;n;p;x;}' fich3.txt
#! /bin/bash
sed -n ' # affichage sur demande uniquement
/indice7/! { # motif absent
h # on garde la ligne dans la mémoire annexe
}
/indice7/{ # motif présent
H # on l'ajoute au contenu de la mémoire annexe
n # on charge la ligne suivante
H # on l'ajoute au contenu de la mémoire annexe
x # on échange le contenu des 2 mémoires
p # on l'affiche
}
' fich3.txt
sed -n '/indice7/! {h;}; /indice7/{H;n;H;x;p;}' fich3.txt
#! /bin/sed -f
:notag # étiquette "pas de motif"
/tag/!{ # si la ligne ne contient pas le motif
1!H # ajouter le contenu à la mémoire annexe, sauf la 1ère ligne
1h # copie la 1ère ligne dans la mémoire annexe
x # échanger le contenu des 2 mémoires tampons
s/\n/ /g # supprimer tous les caractères de nouvelle ligne (\n)
x # échanger à nouveau le contenu des 2 mémoires tampons
$b lastline # se brancher à l'étiquette "dernière ligne"
d # effacer le contenu de l'espace de travail
}
/tag/{ # si la ligne contient le motif
x # échanger le contenu des 2 mémoires tampons
/^$/!p # si la ligne n'est pas vide, l'afficher
$b lastline # se brancher à l'étiquette "dernière ligne"
d # effacer le contenu de l'espace de travail
b notag # se brancher à l'étiquette "pas de motif"
}
:lastline # étiquette "dernière ligne"
x # échanger le contenu des 2 mémoires tampons
p # afficher le contenu de l'espace de travail
sed -n ':notag;/tag/!{1!H;1h;x;s/\n/ /g;x;$b lastline;d;};/tag/{x;/^$/!p;$b lastline;d;b notag;};:lastline;x;p;'
Pattern blablabla blablabla blu ToDelete << Ligne à effacer ToDelete << Ligne à effacer Pattern blablabla blablabla blo ToDelete << Ligne à effacer ToDelete << Ligne à effacer Pattern blablabla blablabla bly ToDelete << Ligne à effacer ToDelete << Ligne à effacer Pattern blablabla blablabla
sed '
/Pattern/ !{ # La ligne ne contient pas le motif
:z # Étiquette
h # On copie l'espace de travail dans la
#+ dans la mémoire annexe
N # On ajoute la ligne suivante
/Pattern$/ !b z # L'espace de travail ne se termine pas par
#+ le motif recherché
#++ alors on se branche à l'étiquette
s/.*\n// # La ligne se termine par le motif, on
#+ supprime tout jusqu'au dernier caractère
#++ représentant un saut de ligne
x # On échange le contenu des 2 mémoires
s/\(.*\)\n.*\n.*$/\1/ # On efface les 2 dernières lignes
G # On ajoute le contenu de la mémoire annexe
#+ à l'espace de travail
}' plop
seq 10 | # on génère 10 lignes à partir de la commande "seq"
sed -n ' # affichage sur demande uniquement
:s # étiquette
1,3 { # tant qu'on n'a pas 3 lignes dans l'espace de travail
N # on ajoute la ligne suivante
b s # on se branche à l'étiquette jusqu'à remplir la condition
}
4,$ { # tant qu'on n'a pas atteint la dernière ligne
N # on ajoute la ligne suivante
P # on affiche la ligne contenue dans l'espace de travail jusqu'au 1er caractère
#+ symbolisant une fin de ligne (\n)
D # puis on l'efface de l'espace de travail
}
'
seq 10 | sed -n ':s;1,3{N;bs};4,${N;P;D}'
#!/bin/sed -nf # Hormis la 1ère ligne 1!G # A jouter le contenu de la mémoire annexe à l'espace de travail # Si la dernière ligne est atteinte $p # Afficher le résultat # Copier le contenu de l'espace de travail dans la mémoire annexe h
sed -n '1! G;$ p;h'
sed -e ' :boucle # étiquette N # on ajoute la ligne suivante $! b boucle # tant que la dernière ligne n'est pas atteinte #+ on se branche à l'étiquette s/\n/--/g # on substitue toutes les fins de ligne par 2 tirets (--) ' fich.txt
sed -e ':boucle;N;$! b boucle; s/\n/--/g'
sed -e '
:boucle # étiquette
s/^.\{1,20\}$/ & / # on substitue le contenu de la ligne par lui même (&) en ajoutant
#+ un espace avant et après
t boucle # tant qu'une substitution a eu lieu, se brancher à l'étiquette
' fich.txt
sed -e ':boucle;s/^.\{1,20\}$/ & /; t boucle'
echo "AABBCCDDEEFF" | sed 's/../&:/g'
AA:BB:CC:DD:EE:FF:
echo "AABBCCDDEEFF" | sed ':z;s/\<..\B/&:/;tz'
$ var="A\nY\nB\nY\nC\nY\nD\nY\nE\nY\nF\nG"
echo -e "$var" |\
sed '
/C/ {
:boucle
N
s/.*Y.*Y.*Y//
T boucle
}
'
sed '/C/{:boucle;N;s/.*Y.*Y.*Y//;T boucle};'
sed '
/C/ {
:boucle
N
s/.*Y.*Y.*Y//
t
b boucle
}
'
sed -e '/C/{:boucle' -e 'N;s/.*Y.*Y.*Y//;t' -e 'b boucle' -e '}'
sed ' # recherche le motif /* ... */
s!/\*.*\*/!! # sur une ligne
/;[ ]*\/\*/ { # sur plusieurs lignes mais ne commençant pas en début de ligne (après
#+ un point virgule suivi éventuellement d'un (ou plusieurs) espace(s)
:z # étiquette pour boucler
N # on ajoute la ligne suivante
s!/\*.*\*/!! # on suprime tout entre /* et */
T z # on teste si une substitution a eu lieu. Dans le cas contraire on boucle
}
/\/\*/,/\*\// d # sur plusieurs lignes
'
echo $A 2007:10:07 16:34:05 echo $A | sed -e ' h # on copie l'espace de travail dans la mémoire annexe s/\(.*\) .*/\1/ # on ne garde que la 1ère partie de l'expression (la date) s/:/-/g # on substitue tous les deux points par des tirets x # on échange le contenu des 2 mémoires s/.*\( .*\)/\1/ # on ne garde que la 2nd partie de l'expression (l'heure) H # on l'ajoute au contenu de la mémoire annexe g # on copie le contenu de la mémoire annexe dans l'espace de travail s/\n// # on supprime le caractère fin de ligne '
echo $A |sed -e 'h;s/\(.*\) .*/\1/;s/:/-/g;x;s/.*\( .*\)/\1/;H;g;s/\n//'
sed '
/# mot-clé/ { # motif recherché
:label # étiquette
/^$/q # si la ligne est vide on quitte
n # on charge dans l'espace de travail la ligne suivante
s/^#// # on supprime le dièse en début de ligne
t label # si une substitution a eu lieu, on se branche à l'étiquette
}
' fichier
sed '/# mot-clé/{:label;/^$/q;n;s/^#//;t label;}'
$ cat plop
àaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïié
ÀaéeÈeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïié
àaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïié
àaéeèeÔoùuïiàaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïié
àaÉeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïiàaéeèeôoùuïié
sed '
h # on copie l'espace de travail dans la mémoire annexe
s/\(^.\{12\}\).*/\1/ # on récupère les 12 premiers caractères de l'espace de travail
y/àâéèêëîïôöùûü/aaeeeeiioouuu/ # on convertit les minuscules
y/ÀÂÉÈÊËÎÏÔÖÙÛÜ/AAEEEEIIOOUUU/ # on convertit les majuscules
x # on échange le contenu des 2 mémoires
s/^.\{12\}\(.*\)/\1/ # on récupère tous les caractères après le 12 ème
x # on échange le contenu des 2 mémoires
G # on ajoute le contenu de la mémoire annexe
s/\n// # on supprime les caractères fin de ligne
' plop
$ cat plop
{"88","6","Trademark2","Model6","6OD","7","false","null","null","1","30","1","40","1","60","1","65","1","65","1","70","1","70","1","70"},
{"89","6","Trademark2","Model6","6PD","7","false","null","null","10","30","10","50","10","70","15","75","25","75","25","80","25","80","25","80"},
sed ' s/,/,\n/5 # On substitue la 5 ème virgule par elle même #+ suivie d'un saut de ligne :s # étiquette s/\(\n.*\)"/\1/ # là on joue sur la gourmandise des regex, la #+ sous-expression englobant tout ce qui se trouve #++ avant le dernier guillemet que l'on remplace donc #+++ par elle même à l'exception du guillemet t s # tant qu'une substitution a eu lieu, on boucle s/\n\(.*\)}/"\1"}/ # et pour finir on remplace tout ce qui se trouve #+ après le saut de ligne jusqu'à l'accolade fermante #++ par ce contenu plus un guillemet et une accolade #+++ la virgule finale n'étant pas dans la LHS est #++++ reportée naturellement ' plop
sed 's/,/,\n/5;:s;s/\(\n.*\)"/\1/;ts;s/\n\(.*\)}/"\1"}/'
sed ' s/\"/§/12 # on substitue le 12 ème guillemet par un caractère quelconque h # on copie la mémoire principale dans la mémoire annexe s/§.*// # on efface ce caractère et tout qui se trouve après x # on échange le contenu des 2 mémoires s/.*§,// # on efface la partie correspondante à la mémoire annexe s/\"//g # on supprime tous les guillemets x # on échange à nouveau le contenu des 2 mémoires G # on ajoute le contenu de la mémoire annexe à la principale s/\n/,/ # on remplace le saut de ligne séparant les 2 mémoires par #+ une virgule s/}/\"}/ # on rajoute le dernier guillemet ' plop
sed -e 'h;s/\"/§/12;s/§.*//;x;s/\"/§/12;s/.*§,//;s/\"//g;x;G;s/\n/,/;s/}/\"}/' plop
$ cat plop
1023 LOGS blabla
12333 LOGS blabla
44 LOGS blabla
2580 LOGS blabla
1458 LOGS blabla
5 LOGS blabla
sed '
/^ / { # seules les lignes commençant par un espace
:boucle # étiquette
s/^ [^[:alnum:]]*/&\n/ # on ajoute un saut de ligne après le dernier espace du 1er champ
s/\([ ]\?\) \{1\}\n/\10/ # on substitue un espace par lui même suivi d'un 0 (zéro)
t boucle # tant qu'une substitution a eu lieu, on boucle
}
'
sed '/^ / {:boucle; s/^ [^[:alnum:]]*/&\n/; s/\([ ]\?\) \{1\}\n/\10/; t boucle}' plop
sed '
/^ / { # seules les lignes commençant par un espace
s/^ [^[:alnum:]]*/&\n/ # on ajoute un saut de ligne après le dernier espace du 1er champ
h # on copie la mémoire principale dans la mémoire annexe
s/\n.*$// # on efface de la mémoire principale tout ce qui suit le saut de
#+ ligne (saut de ligne compris)
s/ /0/g # on substitue tous les espaces par des 0 (zéros)
x # on échange le contenu des 2 mémoires
s/.*\n// # on efface cette fois ci tout ce qui précède le saut de ligne
#+ (saut de ligne compris)
x # on échange à nouveau le contenu des 2 mémoires
G # on copie le contenu de la mémoire annexe à la suite de la
#+ mémoire principale
s/\n// # et on supprime le saut de ligne
}
'
sed '/^ / {s/^ [^[:alnum:]]*/&\n/;h;s/\n.*$//;s/ /0/g;x;s/.*\n//;x;G;s/\n//}' plop
echo -e "A\nB\nC\nD\nE\nF\nG" | sed '/B/,/F/ c\DELETED'
Ligne n° 1 Ligne n° 2 Ligne n° 3 Ligne n° 4 Ligne n° 5 Ligne n° 6 Ligne n° 7 Ligne n° 8 Ligne n° 9 Ligne n° 10
Ligne n° 1 Ligne n° 2 # commentaire1 # Ligne n° 3 Ligne n° 4 Ligne n° 5 # La prochaine ligne est vide (6) # commentaire2 # Ligne n° 7, la ligne précédente est vide (6) Ligne n° 8 Ligne n° 9 # La prochaine ligne est vide (11) Ligne n° 11 # La ligne précédente est vide (10) Ligne n° 12 Ligne n° 13 Ligne n° 14
Ligne n° 1 tag : indice1 indice2 indice3 Ligne n° 2 tag : Ligne n° 3 tag : Ligne n° 4 tag : indice4 indice5 Ligne n° 5 tag : Ligne n° 6 tag: indice6 Ligne n° 7 tag : Ligne n° 8 tag : indice7 indice8 indice9 indice10 Ligne n° 9 tag : Ligne n° 10 tag :
Ubuntu 31000 Toulouse Mandriva 34000 Montpellier SuSE 66000 Perpignan Debian 31130 Balma Gentoo 34500 Béziers Slackware 66100 Collioure Fedora 31400 Muret RedHat 34200 Agde Kaella 66500 Elne
-- Pour toutes correspondances, veuillez vous adressez à : (substituez "<moderateur>" par le nom du modérateur adéquat) <moderateur>@commentcamarche.com Merci de votre attention. L'équipe CCM
#! /bin/sed -f
1 h # chargement 1ère ligne mémoire secondaire
1 d # effacement 1ère ligne
5 { # sélectionner sur la ligne 5
G # ajouter le contenu de la mémoire secondaire à la mémoire principale
N # ajouter la ligne suivante (la 6)
s/\n/ /g # substituer tous les sauts de ligne (\n) par un espace
}
# Sur une seule ligne :
# sed -n '1 h; 1 d; 5 { G; N; s/\n/ /g};P' fich.txt
Combien cela coûte-t-il au total ? Quelles aides apportent l'état et les acteurs du marché pour alléger cette charge non choisie ? Tous les détails sur Commentçamarche.net.