Sed
C’est l’outil absolu pour modifier du texte en le passant par un pipe ! Ou pour effectuer des changements en masses sur un fichier sans l’ouvrir. Bref, comme le dit l’adage : « Sed, c’est bien » 😁
Il est possible de faire des trucs de tarés avec (hey, c’est pas juste un truc pour faire des substitutions à coup d’expressions rationnelles, c’est un vrai éditeur de texte, on peut se balader dans le texte, faire des copier/coller, etc).
Syntaxe de base
Avec un fichier :
sed <commande> fichier.txt [fichier2.txt] [fichier3.txt]
En utilisant la sortie d’une autre commande :
find . -name \*.txt | sed <commande>
NB : sed
, par défaut, ne modifie pas le fichier utilisé.
Il affichera sur la sortie standard le fichier modifié par la commande passée à sed
.
Si on souhaite que le fichier soit modifié, on utilise l’option --in-place
ou son abbréviation -i
(on peut indifféremment placer l’option avant ou après la commande) :
sed <commande> --in-place fichier.txt
sed -i <commande> fichier.txt
Expression régulières
Si sed
est un éditeur de texte (son nom veut dire Stream EDitor) et qu’il est utilisable en lui donnant des commandes équivalentes à « Va à ligne 3, supprime 4 caractères, descend à la ligne suivante… », on l’utilise souvent avec des expressions régulières.
Rappel sur les expressions régulières
Les expressions régulières permettent de rechercher des correspondances avec un motif, écrit avec une syntaxe spéciale.
Les éléments de syntaxe suivants appartiennent aux Perl Compatible Regular Expression (PCRE), qui sont le standard de la très grande majorité des langages de programmation.
sed
utilisant une syntaxe légèrement différente, certains caractères devront être échappés (voir plus bas).
NB : j’ai placé les expressions régulières de cette section entre des /
pour les distinguer des chaînes de caractères simples.
-
.
: correspond à un caractère, n’importe lequel././
correspondra à tout sauf à une chaîne vide -
?
: quantificateur, modifie la correspondance du caractère qui le précède : celui ci peut être présent zéro ou une fois./a?/
correspondra à une chaîne vide ou àa
-
+
: quantificateur : le caractère précédent sera présent une ou plusieurs fois./a+/
correspondra àa
,aa
,aaa
… -
*
: quantificateur : le caractère précédent sera présent zéro ou plusieurs fois./a*/
correspondra à une chaîne vide, àa
,aa
,aaa
… -
{n}
: quantificateur : le caractère précédent sera présentn
fois./a{3}/
correspondra àaaa
-
{n,m}
: quantificateur : le caractère précédent sera présent den
àm
fois./a{3,5}/
correspondra àaaa
,aaaa
ouaaaaa
-
{n,}
: quantificateur : le caractère précédent sera présent au moinsn
fois./a{3,}/
correspondra àaaa
,aaaa
,aaaaa
,aaaaaa
… -
|
: séparateur d’expression./bonjour|hello/
correspondra àbonjour
ou àhello
-
[^liste]
: correspond aux caractères n’étant pas entre crochets./[^ae]/
correspondra à n’importe quel caractère sauf àa
et àe
-
[liste]
: correspond à un des caractères entre crochets./[ae]/
correspondra àa
ou àe
. Pour que le caractère^
soit un choix possible, il faut le placer à une autre place que la première place :[liste^]
,[lis^te]
… On peut aussi spécifier des plages de caractères :[0-9a-zA-Z]
-
^
: ancre, correspond au début de la ligne./^a/
correspondra àa
si celui-ci est le premier caractère de la ligne -
$
: ancre, correspond à la fin de la ligne./a$/
correspondra àa
si celui-ci est le dernier caractère de la ligne -
(…)
: groupe l’expression. On peut s’en servir, par exemple, pour capturer des éléments (ce qui permet de les réutiliser plus tard) ou faire des sous-expressions./Bonjour (foo|bar), ça va \?/
correspondra àBonjour foo, ça va ?
et àBonjour bar, ça va ?
Pour utiliser les caractères de manière littérale (exemple : pour correspondre à un point), on les échappera avec un \
. /\./
correspondra au caractère point (.
).
Caractères à échapper dans sed
La version GNU de sed
utilise les Basic Regular Expression (BRE), qui ont une syntaxe légèrement différentes des PCRE.
Certains caractères doivent donc être échappés dans les BRE, qui sont utilisables tels quels pour des PCRE :
- le quantificateur
+
. Exemple :/a\+/
- le quantificateur
?
. Exemple :/a\?/
- le quantificateur
{i}
. Exemple :/a\{5\}/
- les parenthèses
(…)
. Exemple :/\(a\)/
- le séparateur d’expressions régulières
|
. Exemple :/a\|b/
Effectuer une substitution de texte
La commande à utiliser est 's/expression régulière/substitution/'
:
sed 's/foo/bar/' foo.txt
Cette commande remplacera la 1ère occurrence de foo
de chaque ligne du fichier par bar
.
Si on souhaite remplacer toutes les occurrences de chaque ligne, on emploie le modificateur g
:
sed 's/foo/bar/g' foo.txt
Si on ne souhaite remplacer que l’occurrence n°X de chaque ligne :
sed 's/foo/bar/X' foo.txt
## Exemple avec la 2e occurrence :
sed 's/foo/bar/2' foo.txt
Si on ne souhaite remplacer l’occurrence n°X de chaque ligne, ainsi que les suivantes :
sed 's/foo/bar/gX' foo.txt
## Exemple avec la 2e occurrence et les suivantes :
sed 's/foo/bar/g2' foo.txt
Ajouter quelque chose au début de chaque ligne :
sed 's/^/FooBar /' foo.txt
Ajouter quelque chose à la fin de chaque ligne :
sed 's/$/ BazQux/' foo.txt
Si on souhaite que l’expression régulière soit insensible à la casse (ex : s
qui correspond aussi à S
), on emploie le modificateur i
:
sed 's/foo/bar/i' foo.txt
On peut utiliser plusieurs modificateurs en même temps :
sed 's/foo/bar/gi' foo.txt
Pour réutiliser ce qui a correspondu à l’expression régulière dans la chaîne de substitution, on utilise le caractère &
:
sed 's/foo/& et bar/' foo.txt
Pour réutiliser ce qui a correspondu à un groupe d’expression, on utilise \1
pour le 1er groupe, \2
pour le 2e groupe… :
sed 's/Bonjour (foo|bar). Il fait beau./Bonsoir \1. À demain./' foo.txt
NB : on peut utiliser d’autres séparateurs que le caractère /
, ce qui rend l’écriture d’une commande plus simple si l’expression régulière ou la substitution comportent des /
: plus besoin de les échapper.
Exemple :
sed 's@/home/foo@/var/bar@' foo.txt
Supprimer des lignes
Supprimer la ligne n
:
sed 'nd' foo.txt
## Exemple avec la 3e ligne :
sed '3d' foo.txt
Supprimer les lignes n
à m
:
sed 'n,md' foo.txt
## Exemple :
sed '3,5d' foo.txt
Supprimer toutes les lignes sauf la ligne n
:
sed 'n!d' foo.txt
## Exemple :
sed '6!d' foo.txt
NB : attention, le caractère !
est un caractère spécial pour bash
(et les autres shells).
Si vous utilisez des apostrophes ('
) pour votre commande sed
, tout ira bien, mais si vous utilisez des guillemets doubles ("
), il faut l’échapper avec un \
.
Supprimer toutes les lignes sauf les lignes n
à m
:
sed 'n,m!d' foo.txt
## Exemple :
sed '6,8!d' foo.txt
Supprimer les lignes qui correspondent à une expression régulière :
sed '/regex/d' foo.txt
## Exemple :
sed '/foobar/d' foo.txt
Pour supprimer les lignes vides, d’un fichier, il suffit d’utiliser l’expression régulière qui signifie que la ligne est vide :
sed '/^$/d' foo.txt
Pour supprimer la première ligne correspondant à une expression régulière, ainsi que toutes les lignes suivantes :
sed '/regex/,$d' foo.txt
## Exemple :
sed '/foobar/,$d' foo.txt
NB : attention encore une fois aux guillemets doubles, il faudrait échapper $
dans cette commande car le shell essayerait d’interpréter $d
comme une variable.
No Comments