sed: techniques
Mis à jour le 28/09/2023

Attention

Ici, tous les exemples ne modifient pas de fichier car:

Si on n’effectue pas sed -i, le résultat est envoyé à la sortie standard​.
Avec -i, le fichier référencé est modifié.
-i/--in-place admet le paramètre facultatif SUFFIX qui permet de créer un fichier backup:
sed --in-place=.bak 's/12/98/' sed-test.txt créera le fichier sed-test.txt.bak

Divers
  • Fonctionne en mode flux pour l’entrée et la sortie. C’est à dire: effectue les traitements ligne par ligne
  • $ référence la dernière ligne​
    exemple: sed '$ a # je suis la nouvelle dernière ligne' /etc/hosts
    a ajoute une ligne après celle référencée (ici $)
    ici, on a l’équivalent de la redirection en mode ajout: >>

Dans les exemples qui suivent, le fichier /etc/hosts contient:

127.0.0.1	localhost
127.0.1.1	hp-cp0318nf

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Recherche par regex​

  • Ne pas hésiter à lire/relire: Expressions régulières: résumé (la partie Extensions telle que \d ne fonctionne pas dans sed)

  • On écrit la regex ainsi: /regex/

  • Suppression de toutes les lignes commençant par #
    sed '/^#/d' /etc/hosts
    
  • Recherche entre 2 lignes
    Suppression à partir de la ligne qui contient la 1ère regex jusqu’à la ligne qui contient la 2ème regex
    sed '/^::1/,/^ff02::1/d' /etc/hosts
    

    Fonctionne aussi avec la recherche par numéro de ligne qu’on peut mixer avec la recherche par regex

    sed '3,5d' /etc/hosts
    

    Même recherche, en utilisant la valeur relative du numéro de ligne en utilisant +

    sed '3,+2d' /etc/hosts
    

    On peut inverser cette recherche avec !:

    sed '2,5!d' /etc/hosts
    

    Ici, il y a utilisation de la commande de suppression d, mais cela marche aussi avec les autres commandes comme le remplacement s

Affichage des lignes sur lesquelles la recherche agit

Il faut utiliser l’option -n et la commande p de sed

sed -n '/^::1/,/^ff02::1/p' /etc/hosts
  • A utiliser avant de faire des modifications ​

  • Devient équivalent à grep -P

Rechercher / Remplacer​

La commande s permet la substitution​

  • sed 's/o/O/' remplace le 1er o minuscule de chaque ligne par O majuscule​
  • sed 's/o/O/g' remplace tous les o minuscule de chaque ligne par O majuscule​
  • sed 's/o/O/2' remplace le 2ème o minuscule de chaque ligne par O majuscule​
backref (“Référence arrière”)

Dans le paramètre's/e1/e2/' e1 et e2 sont des regex

Si e1 contient des sous-expressions entre parenthèses, on peut les référencer dans e2 via leur numéro précédé du caractère \ (l’index va de 1 à 9, au delà, il faut utiliser autre chose que sed)

Exemple: Remplacer “256” par “512” puis “512” par “1024” dans une ligne (comme dans un fichier de configuration java)

echo 'des mots -Xms256m -Xmx512m encore des mots' | sed -E 's/(.*Xms)([0-9]+)(.*Xmx)([0-9]+)(.*)$/\1512m\31024m\5/'

Ici il faut mettre -E en option de sed, sans celle-ci ça ne marche et je ne sais pas pourquoi !

Lorsque la regex de recherche est unique, on peut utiliser & pour substituer son expression

echo 'We adopted a cat yesterday. The cat is pretty playful.' | sed 's/cats\?\b/"little &"/g'

Translittération

Concept utilisé par le code César (remplacer des caractères par un autre)

Échanger certains caractères avec d’autres caractères​

echo 'échanger des caractères​' | sed -re 'y/éèêà/eeea/'

Technique avancé

Supposons que nous ayons un fichier HTML et que nous voulions supprimer les balises pour ne garder que le texte

balises.html

<html 
   lang="fr" 
   comment="cette balise est sur plusieurs lignes">

<head>
  <title>Test SED</title>
</head>

<body>
  <h1>Du contenu pour la page HTML</h1>  <h2>Un titre</h2>
  <strong><pre>hello world</pre></strong>
</body>

</html>

sed -re 's/<[^>]*>//g' balises.html est simple mais ne traite pas le cas d’une balise étendue sur plusieurs lignes

sortie de la commande

<html 
   lang="fr" 
   comment="cette balise est sur plusieurs lignes">


  Test SED



  Du contenu pour la page HTML  Un titre
  hello world




sed -re ':start s/<[^>]*>//g; /</ {N; b start}' balises.html fonctionne

sortie de la commande




  Test SED



  Du contenu pour la page HTML  Un titre
  hello world




Explications

  • On va commencer une boucle chaque fois que la regex est détectée
  • On déclare une étiquette (pour les anciens comme en assembleur) -> :start
  • N indique qu’il faut insérer la ligne suivante dans le traitement de la ligne en cours​
  • /</ est ici comme le test de terminaison de la boucle (mais c’est plus complexe)

Commande pour obtenir le même résultat sans les espaces intempestifs sur chaque ligne (trim) et les lignes vides

sed -re ':start s/<[^>]*>//g; /</ {N; b start}' balises.html|sed '/^$/d'|sed -E 's/^[ ]*(.+)[ ]*$/\1/'

Autre exemple

source https://www.gnu.org/software/sed/manual/html_node/Branching-and-flow-control.html

test.txt

All the wor=
ld's a stag=
e,
And all the=
 men and wo=
men merely =
players:
They have t=
heir exits =
and their e=
ntrances;
And one man=
 in his tim=
e plays man=
y parts.
sed ':x ; /=$/ { N ; s/=\n//g ; bx }' test.txt

results matching ""

    No results matching ""