La commande sed

sed

La commande sed (stream editor) est un éditeur de texte non intéractif. Elle permet d'automatiser le traitement de fichiers texte.

Etiquettes: 

Utilisation de la commande sed

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 :

  • Une partie adresse qui permet de spécifier sur quelles lignes doit s'effectuer la commande.
  • La commande à exécuter.
  • Les arguments de la commande.

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]
texte\[entrée]
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

Utilisation de sed en ligne de commande

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 (delete)

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 (print)

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 (write)

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
$

Négation d'une commande (!)

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 (substitution)

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

 

 

 

 

 

 

 

 

 

 

 

Etiquettes: 

Script sed

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  ---------------
$

  • Ligne 1 : Suppression de la première ligne du fichier.
  • Ligne 2 : Affichage du contenu des lignes 3 à 5 du script avant la ligne 2 du fichier.
  • Ligne 6 : Mise en forme des données du fichier
  • Ligne 7 : Identique à la ligne 6 mais avec la prise en compte des départements de La Corse
  • Ligne 8 : Affichage du contenu des lignes 9 à 11 du script après la dernière ligne ($) du fichier.

$ 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
---------------
$

Etiquettes: