La commande sed (stream editor) est un éditeur de texte non intéractif. Elle permet d'automatiser le traitement de fichiers texte.
Syntaxe de base :
sed [-n] action [fichier1 fichier2 ... fichierx]
sed [-n] -e action1 [-e action2 ...] [fichier1 fichier2 ... fichierx]
sed -f script-sed [fichier1 fichier2 ... fichierx]
Les actions spécifiées sont exécutées sur chaque ligne du ou des fichiers. Le résultat du traitement est affiché sur la sortie standard. Si plusieurs actions sont spécifiées sur la ligne de commande, chacune doit être précédée de l'option -e.
La commande sed ne modifie pas le fichier d'origine sauf si elle est exécutée avec l'option -i.
Syntaxe d'une action :
[adresse[,adresse]] commande [arguments]
Une action est syntaxiquement composée de :
Syntaxe d'une adresse :
Type d'adresse | Lignes traitées |
---|---|
Aucune adresse | Toutes les lignes |
Adresses de type 1 | |
n | Ligne n. |
$ | Dernière ligne. |
/ERb/ | Lignes correspondant à l'expression régulière |
Adresses de type 2 | |
n1, n2 | Ligne n1 jusqu'à ligne n2. |
/ERb1/,/ERb2/ | La première ligne traitée sera la première trouvée correspondant à ERb1. Le traitement se poursuivra sur toutes les lignes jusqu'à ce que sed rencontre une ligne correspondant à ERb2. Cette dernière sera également traitée. |
Syntaxe de la commande :
Commande | Argument | Type d'adresse supportée (maximum) | Signification |
---|---|---|---|
d | Aucun | 2 | Ne pas afficher les lignes spécifiées (delete). |
p | Aucun | 2 | Afficher les lignes spécifiées (print). |
s | /ERb/remplacement/[g] | 2 | Effectuer une substitution sur les lignes spécifiées (substitute). Le caractère optionnel "g" indique si la substitution doit être globale sur les lignes. |
w | fichier | 2 | Ecrire les lignes spécifiées dans un fichier (write). |
= | Aucun | 1 | Afficher le numéro de la ligne spécifiée. |
Dans les commandes ci-dessous, l'antislash rend le caractère "saut de ligne" invisible, ce qui permet de pouvoir spécifier plusieurs lignes de texte. Le dernier saut de ligne n'est pas masqué et représente la fin de la commande. | |||
a\ |
texte\[entrée] |
1 | Ajouter les lignes de texte après chaque ligne spécifiée (add). |
i\ |
texte\[entrée] texte\[entrée] texte [entrée] |
1 | Insérer les lignes de texte avant chaque ligne spécifiée (insert). |
c\ |
texte\[entrée] texte\[entrée] texte [entrée] |
2 | Remplacer les ligne spécifiées par les lignes de texte (change). |
Négation de la commande | |||
!commande | La commande s'exécutera sur toutes les lignes sauf celles spécifiées dans l'adresse. |
Exemples avec le fichier depts2012.txt (téléchargeable sur le site de l'INSEE à cette adresse : http://isbeta.fr/f8c21)
$ cat depts2012.txt
REGION DEP CHEFLIEU TNCC NCC NCCENR
82 01 01053 5 AIN Ain
22 02 02408 5 AISNE Aisne
83 03 03190 5 ALLIER Allier
93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence
93 05 05061 4 HAUTES-ALPES Hautes-Alpes
93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes
82 07 07186 5 ARDECHE Ardèche
...
11 94 94028 2 VAL-DE-MARNE Val-de-Marne
11 95 95500 2 VAL-D'OISE Val-d'Oise
01 971 97105 3 GUADELOUPE Guadeloupe
02 972 97209 3 MARTINIQUE Martinique
03 973 97302 3 GUYANE Guyane
04 974 97411 0 LA REUNION La Réunion
06 976 97608 0 MAYOTTE Mayotte
$
La commande d permet de ne pas afficher à l'écran les lignes sélectionnées par la partie adresse.
Exemple :
Ne pas afficher les lignes contenant les caractères de a à h (en minuscule)
$ sed '/[a-h]/d' depts2012.txt
REGION DEP CHEFLIEU TNCC NCC NCCENR
82 01 01053 5 AIN Ain
73 46 46042 2 LOT Lot
$
La commande p permet d'afficher à l'écran les lignes sélectionnées par la partie adresse. Par défauf, sed affiche également tout le contenu du fichier. Pour modifier ce comportement, il faut utiliser l'option -n.
Exemple :
Afficher les lignes 1 à 4. Par défaut, sed affiche en plus tout le contenu du fichier. Les lignes demandées apparaissent donc en double.
$ sed '1,4p' depts2012.txt
REGION DEP CHEFLIEU TNCC NCC NCCENR
REGION DEP CHEFLIEU TNCC NCC NCCENR
82 01 01053 5 AIN Ain
82 01 01053 5 AIN Ain
22 02 02408 5 AISNE Aisne
22 02 02408 5 AISNE Aisne
83 03 03190 5 ALLIER Allier
83 03 03190 5 ALLIER Allier
93 04 04070 4 ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence
93 05 05061 4 HAUTES-ALPES Hautes-Alpes
93 06 06088 4 ALPES-MARITIMES Alpes-Maritimes
....
$
L'option -n permet de ne pas afficher le reste du fichier.
$ sed -n '1,4p' depts2012.txt
REGION DEP CHEFLIEU TNCC NCC NCCENR
82 01 01053 5 AIN Ain
22 02 02408 5 AISNE Aisne
83 03 03190 5 ALLIER Allier
$
Il est également possible d'afficher 1 ligne toutes les n lignes
$ sed -n '1~4p' depts2012.txt
Cette commande permet d'afficher à partir de la ligne 1 du fichier puis toutes les 4 lignes, c'est à dire les lignes 1, 5, 9, 13 etc etc
$ sed -n '0~4p' depts2012.txt
Cette commande permet d'afficher à partir de la ligne 4 du fichier puis toutes les 4 lignes, c'est à dire les lignes 4, 8, 12, 16 etc etc
Pour info, ce type d'adressage est valable pour les commandes delete, print, write
La commande suivante permet de rechercher un motif précis et d'afficher uniquement la ligne suivante.
$ sed -n '/ANSWER SECTION/{n;p}' <(dig a quennec.fr)
quennec.fr. 906 IN A 51.159.70.99
La première partie '/ANSWER SECTION/' correspond au motif recherché.
Ensuite, '{n;p}', un bloc d'instruction qui est exécuté si le motif recherché est trouvé.
La command 'n' permet de sauter à la ligne suivante.
La commande 'p' permet d'afficher la ligne courante.
et si l'on souhaite afficher plusieurs lignes après le motif recherché
$ dig any quennec.fr | sed -n '/ANSWER SECTION/{:a ; n ; /^$/q ; p ; ba}'
quennec.fr. 3183 IN A 51.159.70.99
quennec.fr. 21400 IN NS ns42.infomaniak.com.
quennec.fr. 21400 IN NS ns41.infomaniak.com.
quennec.fr. 21400 IN SOA ns41.infomaniak.com. hostmaster.infomaniak.ch. 2024091604 10800 3600 605800 86400
quennec.fr. 3400 IN MX 5 mta-gw.infomaniak.ch.
quennec.fr. 3368 IN TXT "v=spf1 a mx ip4:99.162.140.135ip4:51.159.70.99 include:spf.infomaniak.ch -all"
Ce qui change vis à vis de la commande précédente:
Dans le bloc d'instruction '{:a ; n ; /^$/q ; p ; ba}', la première commande ':a' permet d'initialiser un label, la commande 'n' permet de passer à la ligne suivante (pas de changement), la commande '/^$/q' permet de mettre fin au traitement dès qu'une ligne vide est rencontrée, la commande 'p' permet d'afficher la ligne en cours de traitement (pas de changement), et enfin, la commande 'ba' permet de revenir au label 'a' précédement initialisé et de continuer le traitement sur la ligne suivante (à voir comme une boucle) etc etc ...
La commande w permet d'écrire dans un fichier les lignes sélectionnées par la partie adresse. Comme pour la commande p, sed affiche également tout le contenu du fichier à l'écran. Pour modifier ce comportement, il faut utiliser l'option -n.
Exemple :
Stocker dans un fichier "depts3x" toutes les villes dont le code postal commence par 3 et dans le fichier "depts6x" toutes les villes dont le code postal commence par 6.
$ sed -n -e '/3[0-9]\{4\}/w depts3x' -e '/6[0-9]\{4\}/w depts6x' depts2012.txt
$ cat depts3x
91 30 30189 2 GARD Gard
73 31 31555 3 HAUTE-GARONNE Haute-Garonne
73 32 32013 2 GERS Gers
72 33 33063 3 GIRONDE Gironde
91 34 34172 5 HERAULT Hérault
53 35 35238 1 ILLE-ET-VILAINE Ille-et-Vilaine
24 36 36044 5 INDRE Indre
24 37 37261 1 INDRE-ET-LOIRE Indre-et-Loire
82 38 38185 5 ISERE Isère
43 39 39300 2 JURA Jura
$ cat depts6x
22 60 60057 5 OISE Oise
25 61 61001 5 ORNE Orne
31 62 62041 2 PAS-DE-CALAIS Pas-de-Calais
83 63 63113 2 PUY-DE-DOME Puy-de-Dôme
72 64 64445 4 PYRENEES-ATLANTIQUES Pyrénées-Atlantiques
73 65 65440 4 HAUTES-PYRENEES Hautes-Pyrénées
91 66 66136 4 PYRENEES-ORIENTALES Pyrénées-Orientales
42 67 67482 2 BAS-RHIN Bas-Rhin
42 68 68066 2 HAUT-RHIN Haut-Rhin
82 69 69123 2 RHONE Rhône
$
Le caractère ! placé devant une commande permet d'exécuter cette dernière sur toutes les lignes sauf sur celles correspondant à la partie adresse.
Exemple :
Ne pas afficher les lignes contenant les caractères de a à h (en minuscule)
$ sed -n '/[a-h]/!p' depts2012.txt
REGION DEP CHEFLIEU TNCC NCC NCCENR
82 01 01053 5 AIN Ain
73 46 46042 2 LOT Lot
$
La commande s permet de substituer une chaine de caractères par une autre sur les lignes sélectionnées par la partie adresse.
Pour substituer des noms de fichiers avec la commande sed, utiliser le pipe '|' comme séparateur à cause du slash '/' dans les noms de fichiers.
$ sed -i "s|/fichier1|/fichier2|g" maListeDeFichiers
Premier exemple :
Remplacer toutes les chaines contenant '-et-' ou '-ET-' par ' & '
$ sed -n '/-et-/p' depts2012.txt
24 28 28085 1 EURE-ET-LOIR Eure-et-Loir
53 35 35238 1 ILLE-ET-VILAINE Ille-et-Vilaine
24 37 37261 1 INDRE-ET-LOIRE Indre-et-Loire
24 41 41018 0 LOIR-ET-CHER Loir-et-Cher
72 47 47001 0 LOT-ET-GARONNE Lot-et-Garonne
52 49 49007 0 MAINE-ET-LOIRE Maine-et-Loire
41 54 54395 0 MEURTHE-ET-MOSELLE Meurthe-et-Moselle
26 71 71270 0 SAONE-ET-LOIRE Saône-et-Loire
11 77 77288 0 SEINE-ET-MARNE Seine-et-Marne
73 82 82121 0 TARN-ET-GARONNE Tarn-et-Garonne
$
$ sed -e 's/-et-/ \& /g' -e 's/-ET-/ \& /g' depts2012.txt | sed -n '/ \& /p'
24 28 28085 1 EURE & LOIR Eure & Loir
53 35 35238 1 ILLE & VILAINE Ille & Vilaine
24 37 37261 1 INDRE & LOIRE Indre & Loire
24 41 41018 0 LOIR & CHER Loir & Cher
72 47 47001 0 LOT & GARONNE Lot & Garonne
52 49 49007 0 MAINE & LOIRE Maine & Loire
41 54 54395 0 MEURTHE & MOSELLE Meurthe & Moselle
26 71 71270 0 SAONE & LOIRE Saône & Loire
11 77 77288 0 SEINE & MARNE Seine & Marne
73 82 82121 0 TARN & GARONNE Tarn & Garonne
$
Second exemple :
Travailler sur le contenu d'une variable.
$ arg=fic1,fic2,fic3
$ echo $arg
fic1,fic2,fic3
$ echo $arg | sed 's/,/ /g' # On remplace les virgules par des espaces
fic1 fic2 fic3
$ liste_arg=$(echo $arg | sed 's/,/ /g')
$ echo $liste_arg
fic1 fic2 fic3
$ for argt in $liste_arg
> do
> echo $argt
> done
fic1
fic2
fic3
$
Troisième exemple :
Le caractère "&" utilisée dans la partie remplacement représente la chaine correspondant à l'expression régulière.
$ tail depts2012.txt
11 91 91228 5 ESSONNE Essonne
11 92 92050 4 HAUTS-DE-SEINE Hauts-de-Seine
11 93 93008 3 SEINE-SAINT-DENIS Seine-Saint-Denis
11 94 94028 2 VAL-DE-MARNE Val-de-Marne
11 95 95500 2 VAL-D'OISE Val-d'Oise
01 971 97105 3 GUADELOUPE Guadeloupe
02 972 97209 3 MARTINIQUE Martinique
03 973 97302 3 GUYANE Guyane
04 974 97411 0 LA REUNION La Réunion
06 976 97608 0 MAYOTTE Mayotte
$ tail depts2012.txt | sed 's/.*/|&|/'
|11 91 91228 5 ESSONNE Essonne|
|11 92 92050 4 HAUTS-DE-SEINE Hauts-de-Seine|
|11 93 93008 3 SEINE-SAINT-DENIS Seine-Saint-Denis|
|11 94 94028 2 VAL-DE-MARNE Val-de-Marne|
|11 95 95500 2 VAL-D'OISE Val-d'Oise|
|01 971 97105 3 GUADELOUPE Guadeloupe|
|02 972 97209 3 MARTINIQUE Martinique|
|03 973 97302 3 GUYANE Guyane|
|04 974 97411 0 LA REUNION La Réunion|
|06 976 97608 0 MAYOTTE Mayotte|
$
Toutes les chaines ont été encadrées par des pipes "|"
Quatrième exemple :
Récupérer les codes postaux et les noms des départements (en majuscule) afin d'effectuer une mise en forme particulière.
Utilisation de la mémorisation grâce aux caractères \( \) afin de les réafficher avec \1 et \2.
$ tail depts2012.txt
11 91 91228 5 ESSONNE Essonne
11 92 92050 4 HAUTS-DE-SEINE Hauts-de-Seine
11 93 93008 3 SEINE-SAINT-DENIS Seine-Saint-Denis
11 94 94028 2 VAL-DE-MARNE Val-de-Marne
11 95 95500 2 VAL-D'OISE Val-d'Oise
01 971 97105 3 GUADELOUPE Guadeloupe
02 972 97209 3 MARTINIQUE Martinique
03 973 97302 3 GUYANE Guyane
04 974 97411 0 LA REUNION La Réunion
06 976 97608 0 MAYOTTE Mayotte
$ tail depts2012.txt | sed "s/^[0-9]\{2\}[ \t]*[0-9]\{2,3\}[ \t]*\([0-9]\{5\}\)[ \t]*[0-9][ \t]*\([-A-Z_\. ']\{1,\}\)[ \t]*.\{1,\}$/Code postal : \1\tDepartement : \2/"
Code postal : 91228 Departement : ESSONNE
Code postal : 92050 Departement : HAUTS-DE-SEINE
Code postal : 93008 Departement : SEINE-SAINT-DENIS
Code postal : 94028 Departement : VAL-DE-MARNE
Code postal : 95500 Departement : VAL-D'OISE
Code postal : 97105 Departement : GUADELOUPE
Code postal : 97209 Departement : MARTINIQUE
Code postal : 97302 Departement : GUYANE
Code postal : 97411 Departement : LA REUNION
Code postal : 97608 Departement : MAYOTTE
$
Cinquième exemple :
Exemples détaillés de l'option g dans la commande de substitution s.
$ arg=val1,val2,val3,val4
$ echo $arg
val1,val2,val3,val4
Remplacement de la globalité des virgules par des espaces grâce à l'option g.
$ echo $arg | sed 's/,/ /g'
val1 val2 val3 val4
Sans l'option g, seule la première virgule rencontrée est remplacée par un espace.
$ echo $arg | sed 's/,/ /'
val1 val2,val3,val4
Le chiffre 1 permet le remplacement de la première virgule rencontrée. Identique à la commande précédente.
$ echo $arg | sed 's/,/ /1'
val1 val2,val3,val4
Le chiffre 3 permet le remplacement de la troisième virgule rencontrée.
$ echo $arg | sed 's/,/ /3'
val1,val2,val3 val4
Un script sed est un fichier texte contenant une suite d'actions sed qui seront exécutées sur les lignes d'un ou plusieurs fichiers passés en paramètre ou sur l'entrée standard de la commande sed.
Toutes les actions sont évaluées et appliquées sur toutes les lignes du ou des fichiers.
Exemple :
$ nl script.sed
1 1d
2 2i\
3 ------------------------\
4 Liste des departements :\
5 ------------------------
6 s/^[0-9]\{2\}[ \t]*[0-9]\{2,3\}[ \t]*\([0-9]\{5\}\)[ \t]*[0-9][ \t]*\([-A-Z_\. ']\{1,\}\)[ \t]*.\{1,\}$/Code postal : \1\tDepartement : \2/
7 s/^[0-9]\{2\}[ \t]*[0-9][A-B][ \t]*\([0-9][A-B][0-9]\{3\}\)[ \t]*[0-9][ \t]*\([-A-Z_\. ']\{1,\}\)[ \t]*.\{1,\}$/Code postal : \1\tDepartement : \2/
8 $a\
9 ---------------\
10 Fin de la liste\
11 ---------------
$
$ sed -f script.sed depts2012.txt
------------------------
Liste des departements :
------------------------
Code postal : 01053 Departement : AIN
Code postal : 02408 Departement : AISNE
Code postal : 03190 Departement : ALLIER
Code postal : 04070 Departement : ALPES-DE-HAUTE-PROVENCE
Code postal : 05061 Departement : HAUTES-ALPES
Code postal : 06088 Departement : ALPES-MARITIMES
Code postal : 07186 Departement : ARDECHE
Code postal : 08105 Departement : ARDENNES
Code postal : 09122 Departement : ARIEGE
Code postal : 10387 Departement : AUBE
Code postal : 11069 Departement : AUDE
Code postal : 12202 Departement : AVEYRON
Code postal : 13055 Departement : BOUCHES-DU-RHONE
Code postal : 14118 Departement : CALVADOS
Code postal : 15014 Departement : CANTAL
Code postal : 16015 Departement : CHARENTE
Code postal : 17300 Departement : CHARENTE-MARITIME
Code postal : 18033 Departement : CHER
Code postal : 19272 Departement : CORREZE
Code postal : 2A004 Departement : CORSE-DU-SUD
Code postal : 2B033 Departement : HAUTE-CORSE
Code postal : 21231 Departement : COTE-D'OR
Code postal : 22278 Departement : COTES-D'ARMOR
Code postal : 23096 Departement : CREUSE
Code postal : 24322 Departement : DORDOGNE
Code postal : 25056 Departement : DOUBS
Code postal : 26362 Departement : DROME
Code postal : 27229 Departement : EURE
Code postal : 28085 Departement : EURE-ET-LOIR
Code postal : 29232 Departement : FINISTERE
Code postal : 30189 Departement : GARD
Code postal : 31555 Departement : HAUTE-GARONNE
Code postal : 32013 Departement : GERS
Code postal : 33063 Departement : GIRONDE
Code postal : 34172 Departement : HERAULT
Code postal : 35238 Departement : ILLE-ET-VILAINE
Code postal : 36044 Departement : INDRE
Code postal : 37261 Departement : INDRE-ET-LOIRE
Code postal : 38185 Departement : ISERE
Code postal : 39300 Departement : JURA
Code postal : 40192 Departement : LANDES
Code postal : 41018 Departement : LOIR-ET-CHER
Code postal : 42218 Departement : LOIRE
Code postal : 43157 Departement : HAUTE-LOIRE
Code postal : 44109 Departement : LOIRE-ATLANTIQUE
Code postal : 45234 Departement : LOIRET
Code postal : 46042 Departement : LOT
Code postal : 47001 Departement : LOT-ET-GARONNE
Code postal : 48095 Departement : LOZERE
Code postal : 49007 Departement : MAINE-ET-LOIRE
Code postal : 50502 Departement : MANCHE
Code postal : 51108 Departement : MARNE
Code postal : 52121 Departement : HAUTE-MARNE
Code postal : 53130 Departement : MAYENNE
Code postal : 54395 Departement : MEURTHE-ET-MOSELLE
Code postal : 55029 Departement : MEUSE
Code postal : 56260 Departement : MORBIHAN
Code postal : 57463 Departement : MOSELLE
Code postal : 58194 Departement : NIEVRE
Code postal : 59350 Departement : NORD
Code postal : 60057 Departement : OISE
Code postal : 61001 Departement : ORNE
Code postal : 62041 Departement : PAS-DE-CALAIS
Code postal : 63113 Departement : PUY-DE-DOME
Code postal : 64445 Departement : PYRENEES-ATLANTIQUES
Code postal : 65440 Departement : HAUTES-PYRENEES
Code postal : 66136 Departement : PYRENEES-ORIENTALES
Code postal : 67482 Departement : BAS-RHIN
Code postal : 68066 Departement : HAUT-RHIN
Code postal : 69123 Departement : RHONE
Code postal : 70550 Departement : HAUTE-SAONE
Code postal : 71270 Departement : SAONE-ET-LOIRE
Code postal : 72181 Departement : SARTHE
Code postal : 73065 Departement : SAVOIE
Code postal : 74010 Departement : HAUTE-SAVOIE
Code postal : 75056 Departement : PARIS
Code postal : 76540 Departement : SEINE-MARITIME
Code postal : 77288 Departement : SEINE-ET-MARNE
Code postal : 78646 Departement : YVELINES
Code postal : 79191 Departement : DEUX-SEVRES
Code postal : 80021 Departement : SOMME
Code postal : 81004 Departement : TARN
Code postal : 82121 Departement : TARN-ET-GARONNE
Code postal : 83137 Departement : VAR
Code postal : 84007 Departement : VAUCLUSE
Code postal : 85191 Departement : VENDEE
Code postal : 86194 Departement : VIENNE
Code postal : 87085 Departement : HAUTE-VIENNE
Code postal : 88160 Departement : VOSGES
Code postal : 89024 Departement : YONNE
Code postal : 90010 Departement : TERRITOIRE DE BELFORT
Code postal : 91228 Departement : ESSONNE
Code postal : 92050 Departement : HAUTS-DE-SEINE
Code postal : 93008 Departement : SEINE-SAINT-DENIS
Code postal : 94028 Departement : VAL-DE-MARNE
Code postal : 95500 Departement : VAL-D'OISE
Code postal : 97105 Departement : GUADELOUPE
Code postal : 97209 Departement : MARTINIQUE
Code postal : 97302 Departement : GUYANE
Code postal : 97411 Departement : LA REUNION
Code postal : 97608 Departement : MAYOTTE
---------------
Fin de la liste
---------------
$