Tutoriel UNIX/LINUX pour la commande sed

Aide à SED, tutorial

Citation
, XML
Auteurs

Abstract

Explications non exhaustives sur l’usage de la commande sed via des exemples pratiques.

 


 

Introduction

 

Cet article, qui sera étendu au fur et à mesure du temps, a pour but d’aider sur la syntaxe de ce mini-monde qu’est la commande sed. Un fichier de base sera utilisé pour expliquer les effets de chaque syntaxe.
Premier avertissement, il existe une différence entre ‘ et ‘ , essentiellement sur les claviers francophones, il se fait que vous pourriez voir toutes vos commandes échouer si vous tapez la commande telle que décrite alors que si vous faites un copier/coller, à apparences identiques, la commande détaillée fonctionnera.
La raison en est simple, les claviers francophones et anglais sont très semblables mais le code ASCII de ‘ est différent. Visuellement, c’est la même chose mais pas pour la machine.
Alors, soit vous reconfigurez votre clavier, soit vous tapez le bon code ASCII via Alt+ ou alors, vous copiez systématiquement le bon ‘.
Dernière solution, plus simple, sur les claviers azerty, utilisez le symbole « ` »  à la place qui est avec la touche µ/£ et acessible grace à la combinaison Alt Gr + µ£ .
En tous les cas, évitez de mélanger dans vos scripts   » ` « et  » ‘  » sinon vous finirez par avoir des problèmes de syntaxe, faites un choix d’entrée de jeux.
 
 
Vous observerez également que plusieurs solutions existent pour un même résultat, que soit via d’autres commandes ou par combinaison (« | ») ou par concaténation dans sed (« ; »).
J’attire également l’attention des développeur que sed est une commande de traitement de fichier, si lors de votre développement, vous soignez le format de vos fichiers de sortie, vous pouvez grandement faciliter leur traitement ou leur analyse ultérieure.

 

Le fichier d’exemple

 
Fichier data.txt
$ cat data.txt
2010/09/21 00:23:19
CALL FOR PROVISIONNING
POST TRANSACTIONS = OCCURENCE 01
TRANSMISSION
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION
2010/09/21 00:23:57
 
 

Les fonctions de découpe: comparaison sed/cut/grep

Permet de n’afficher les colonnes 1 à 19 sur les lignes contenant 2010:
$ cut -c1-19 data.txt | grep -i 2010
$ cut -c1-19 data.txt | sed ‘/^2010/!d’ data.txt
2010/09/21 00:23:19
2010/09/21 00:23:57
Sur les lignes contenant 2010, afficher les colonnes 1 à 19
$ grep -i 2010 data.txt| cut -c1-19
$ sed ‘/^2010/!d’ data.txt| cut -c1-19
2010/09/21 00:23:19
LOUVAIN/PARK PLAZA/
EVERE/PARK COMMUNE/
WOLUWE ST LAMBERT/W
2010/09/21 00:23:57
Permière leçon, chou vert et vert chou donne rarement le même résultat selon le sens choisi
 

Les premières extractions

 
$ sed ‘/^2010/!d’ data.txt| sed ‘s ………$  ‘
$ sed ‘/^2010/!d;s ………$  ‘ data.txt
2010/09/21
2010/09/21

$ sed ‘/^EUROS/!d’ data.txt ne donne rien car il n’y a pas d’espace autour de « EUROS »
$ sed ‘/^END/!d’ data.txt
END TRANSMISSION
Parce que le mot « END » est isolé.
La même commande qui donne les numéros d’entrées seulement
$ sed ‘/^ECHO/!d;s/ECHO//g’ data.txt
 1
 2
 3

Extraction, modification et purification de données

Ici, je vais extraire une communication standard en lui ôtant son habillage de « +++ » ainsi que la transformer.
$ grep -i « + » data.txt | tr -d « + »
$ grep -i « + » data.txt |sed ‘s …  ‘|sed ‘s …$  ‘
$ sed ‘/^+/!d’ data.txt|sed ‘s …  ‘|sed ‘s …$  ‘
$ sed ‘/^+/!d;s …  ;s …$  ‘ data.txt
104/5190/66613
101/3423/65789
Autre commande qui extrait entre deux bornes:
$ echo « Extraction de donnees mineralogiques CACK-667 mal parquee » | sed -e « s/.*mineralogiques//;s/mal.*// »
CACK-667
Ou alors, extraire une donnée entre deux bornes connues:
$ head -6 data.txt| tail -1 |sed -e « s/.*DUPONT//;s/BECK-354.*// »
/MARCEL/
 
$ sed ‘/^+/!d;s …  ;s …$  ;s////g’ data.txt
104519066613
101342365789
Une variante qui supprime les « / » et met un espace après chaque caractère
$ sed ‘/^+/!d;s …  ;s …$  ;s////g;s/./& /g’ data.txt
1 0 4 5 1 9 0 6 6 6 1 3
1 0 1 3 4 2 3 6 5 7 8 9

Va insérer une ligne vide après chaque ligne du fichier
$ sed G data.txt

Insère une ligne vide après chaque ligne contenant « + »
$ sed ‘/+/G’ data.txt
2010/09/21 00:23:19
CALL FOR PROVISIONNING
POST TRANSACTIONS = OCCURENCE 01
TRANSMISSION
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++

ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
+++101/3423/65789+++

ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION
2010/09/21 00:23:57
 
Extraction de toutes les lignes contenant « : » et supression de l’heure
$ grep -i « : »  data.txt| sed ‘1,$s/………$//’
2010/09/21
2010/09/21
Extraction de toutes les lignes contenant « EUROS » et suppression du timestamp

$ grep -i « EUROS » data.txt | sed ‘1,$s/…………$//’
LOUVAIN/PARK PLAZA/25 EUROS/
EVERE/PARK COMMUNE/25 EUROS/
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/

Extraction de toutes les lignes contenant « EUROS » et suppression du timestamp ainsi que du tarif

$ grep -i « EUROS » data.txt | sed ‘1,$s/………………….$//’
LOUVAIN/PARK PLAZA
EVERE/PARK COMMUNE
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER

Suppression de « / » au sein de la ligne

$ grep -i « EUROS » data.txt |  sed ‘s/’/’//g’
LOUVAINPARK PLAZA25 EUROS201009201450
EVEREPARK COMMUNE25 EUROS201009201030
WOLUWE ST LAMBERTWOLUWE SHOPPING CENTER40 EUROS201009201117

$ head -6 data.txt| tail -1 |sed -e « s/.*DUPONT//;s/BECK-354.*// »|sed ‘s/’/’//g’

MARCEL

$ grep -i « EUROS » data.txt |  sed ‘s////g’
LOUVAINPARK PLAZA25 EUROS201009201450
EVEREPARK COMMUNE25 EUROS201009201030
WOLUWE ST LAMBERTWOLUWE SHOPPING CENTER40 EUROS201009201117

Vous observerez que dans ce cas-ci, les deux syntaxes ont le même effet

Affichage de la ligne du lieu, tarif et moment, sans la mention « EUROS »

$ grep -i « EUROS » data.txt |  sed ‘s/EUROS//g’
LOUVAIN/PARK PLAZA/25 /201009201450
EVERE/PARK COMMUNE/25 /201009201030
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 /201009201117

Vous observerez que sélectionner une ligne par sed en utilisant ^EUROS n’a pas fonctionné mais pour les transformation par contre, cela fonctionne.
 
 

Numéroter les lignes de mon fichier (visuellement)

Va numéroter les lignes du fichier. Attention, dans ce cas-ci concaténer les deux commandes sed n’est pas possible.
$ sed = data3.txt | sed ‘N;s/n/t/’

Va numéroter uniquement les lignes non vides du fichier. Attention, dans ce cas-ci concaténer les deux commandes sed n’est pas possible.
$ sed ‘/./=’ data.txt | sed ‘/./N;s/n/ /’

Donne le nombre de lignes du fichier
$ sed -n ‘$=’ data.txt
17

Va lister les numéros de lignes contenant l’élément recherché
$ sed -n ‘/ECHO/=’ data.txt
5
9
1

 

Extraction sur base de position et alphanumérique

Va extraire les plaques minéralogiques présentes dans le fichier
$ grep -i « – » data.txt| sed ‘s/^.*([A-Z]{4}-[0-9]{3}).*$/1/’
BECK-354
CACK-667
MOGU-567

Va extraire les mêmes plaques minéralogiques mais en prenant seulement les 3 première lettres
$ grep -i « – » data.txt| sed ‘s/^.*([A-Z]{3}-[0-9]{3}).*$/1/’
ECK-354
ACK-667
OGU-567

 

Extraction de données sur base de leur position ou de leur numéro de ligne

$ head -16 data.txt | tail -12
$ sed ‘1,4d;$d’ data.txt
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION
L’inverse, juste la première et la dernière ligne
$ sed ‘2,16d;!p’ data.txt
2010/09/21 00:23:19
2010/09/21 00:23:57

Ici, on application aux communications, tout en changeant les « + » en « * »
$ sed ‘/^+/!d’ data.txt|sed -e ‘s/+/*/g’
$ sed -e ‘/^+/!d;s/+/*/g’ data.txt
***104/5190/66613***
***101/3423/65789***

 

Remplacement conditionnel

Remplace « EUROS » par « DOLLARS » quand la valeur « 201009201030 » est présente dans la ligne
$ sed ‘/201009201030/s/EUROS/DOLLARS/g’ data.txt
2010/09/21 00:23:19
CALL FOR PROVISIONNING
POST TRANSACTIONS = OCCURENCE 01
TRANSMISSION
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 DOLLARS/201009201030
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION
2010/09/21 00:23:57

Visualisation du fichier complet modifié (peut-être sauvé dans un autre fichier)

Permet de visualiser seulement le fichier entier avec une permutation « + » vers « * »
$ sed ‘/^+/!d’ data2.txt|sed -e ‘s/+/*/g’ <data.txt
2010/09/21 00:23:19
CALL FOR PROVISIONNING
POST TRANSACTIONS = OCCURENCE 01
TRANSMISSION
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
***104/5190/66613***
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
***101/3423/65789***
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION
2010/09/21 00:23:57

La commande suivante sauve votre visualisation dans une version 2
$ sed ‘/^+/!d’ data2.txt|sed -e ‘s/+/*/g’ <data.txt >data2.txt

Retrait conditionnel

Retire toutes les lignes vides du fichier
$ sed ‘/./!d’ data.txt
$ sed ‘/./!d’ data.txt
 

Ajouter des caractères dans une ligne

Rajoute au début de toute les lignes contenant « + » le mot « COMMUNICATION », sans afficher les 4 premières lignes ni la dernière ligne
$ sed -n ‘/*/ s//COMMUNICATION /;5,$p;$d’ data.txt
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
COMMUNICATION **104/5190/66613***
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
COMMUNICATION **101/3423/65789***
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
END TRANSMISSION

Affichage à conditions multiples

N’affiche que les lignes ne contenant pas « EUROS » et « 2010 », ni les 4 premières
$ sed -n ‘5;$p;$d;/EUROS/d;/2010/d;$d’ data.txt
ECHO 1
DUPONT/MARCEL/BECK-354
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
END TRANSMISSION
 
Permet de n’afficher que les lignes ne contenant pas de chiffres en fin de ligne
$ sed ‘/[0-9/][0-9]*$/d’ data.txt
CALL FOR PROVISIONNING
TRANSMISSION
+++104/5190/66613+++
+++101/3423/65789+++
END TRANSMISSION
Ceci permet de n’afficher que les lignes ne contenant pas de lettre en fin de ligne
$ sed ‘/[A-Z/][A-Z]*$/d’ data.txt
2010/09/21 00:23:19
POST TRANSACTIONS = OCCURENCE 01
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
2010/09/21 00:23:57
 

Travailler des données ensemble

Afficher date et heure de début et de fin
$ sed ‘2,16d’ data.txt
2010/09/21 00:23:19
2010/09/21 00:23:57
Afficher seulement Heure de début et de fin, sans les secondes
$ sed ‘2,16d;s ………..  ;s …$  ‘ data.txt
00:23
00:23

Permet de n’afficher que les lignes ne contenant pas de chiffres en fin de ligne
$ sed ‘/[0-9/][0-9]*$/d’ data.txt
CALL FOR PROVISIONNING
TRANSMISSION
+++104/5190/66613+++
+++101/3423/65789+++
END TRANSMISSION
Ceci permet de n’afficher que les lignes ne contenant pas de lettre en fin de ligne
$ sed ‘/[A-Z/][A-Z]*$/d’ data.txt
2010/09/21 00:23:19
POST TRANSACTIONS = OCCURENCE 01
ECHO 1
DUPONT/MARCEL/BECK-354
LOUVAIN/PARK PLAZA/25 EUROS/201009201450
+++104/5190/66613+++
ECHO 2
LARMIER/KARL/CACK-667
EVERE/PARK COMMUNE/25 EUROS/201009201030
+++101/3423/65789+++
ECHO 3
PATT/PRATT/MOGU-567
WOLUWE ST LAMBERT/WOLUWE SHOPPING CENTER/40 EUROS/201009201117
2010/09/21 00:23:57

 Retour au Vade-mecum unix

 
By Hugues CREPIN : Site principal