Gentoo Logo

Avertissement : La version originale de cet article a été publiée sur IBM developerWorks et est la propriété de Westtech Information Services. Ce document est une traduction de la mise à jour de la version originale de l'article réalisée par l'équipe de documentation Gentoo et contient quelques améliorations proposées par l'équipe de documentation de Gentoo Linux.
Ce document n'est pas activement maintenu.


Sed par l'exemple — Première partie

Table des matières :

1.  Prise en main de Sed, puissant éditeur UNIX

Le choix de l'éditeur

Dans le monde UNIX, nous disposons de beaucoup d'options quand il s'agit d'éditer des fichiers. Il vous suffit de réfléchir et vous verrez des noms comme vi, emacs ou jed vous venir à l'esprit, mais ce ne sont que des exemples parmi d'autres. Nous avons tous un éditeur de texte favori (accompagné de raccourcis claviers adaptés à vos habitudes) que nous avons appris à utiliser et que nous aimons. Avec notre éditeur bien aimé nous pouvons réaliser n'importe quelle tâche d'administration liée à la programmation ou à l'administration UNIX.

Si les éditeurs interactifs sont puissants, ils ont aussi des limitations. Si leur nature interactive peut être une force, cela peut aussi se révéler être une faiblesse. Prenez par exemple une situation dans laquelle vous devez effectuer des modifications similaires sur un groupement de fichiers. Vous pouvez lancer instinctivement votre éditeur favori et réaliser une grosse quantité d'éditions de fichiers à la main, opération longue et répétitive. Mais il existe un meilleur moyen.

Utiliser Sed

Ce serait bien si nous pouvions automatiser le processus d'édition des fichiers et ainsi pouvoir les éditer en ligne de commande, voire même écrire des scripts qui permettent d'effectuer des modifications sophistiquées sur des fichiers existants. Heureusement pour nous, dans ce genre de situation, il existe une solution. Cette solution s'appelle Sed.

Sed est un éditeur de flux léger inclus dans presque tous les systèmes UNIX, notamment Linux. Sed dispose de nombreuses fonctionnalités intéressantes. Tout d'abord, il est très léger, généralement plusieurs fois plus petit que votre éditeur préféré. Ensuite, comme Sed est un éditeur de flux, il peut éditer les données qu'il reçoit depuis l'entrée standard stdin ou depuis un « pipe ». Vous n'avez donc pas besoin d'avoir les données sauvées dans un fichier pour pouvoir les éditer. Comme les données peuvent être traitées en ligne de commande, il est très facile d'utiliser Sed dans une longue ligne de commande d'un script Shell. Essayez donc d'en faire autant avec votre éditeur favori.

GNU sed

Heureusement pour nous autres utilisateurs de Linux, l'une des meilleures versions de Sed existantes se trouve être GNU sed, actuellement dans sa version 3.02. Toutes les distributions Linux contiennent GNU sed ou, du moins, devraient le contenir. GNU sed est populaire non seulement parce que ses sources peuvent être distribuées librement, mais aussi parce qu'il dispose de nombreuses extensions efficaces et sympathiques vis-à-vis du standard POSIX. GNU sed ne souffre pas des nombreuses limitations que l'on trouve dans les récentes solutions propriétaires de Sed, comme, par exemple, une limite sur la longueur des lignes (GNU sed gère avec aisance les lignes de toutes tailles).

La version GNU sed la plus récente

Lors de mes recherches pour écrire cet article, j'ai remarqué que beaucoup de fans de Sed sur Internet faisaient référence à GNU sed 3.02a. Curieusement je n'arrivais pas à trouver cette version sur ftp://ftp.gnu.org (voir les Ressources de cet article pour obtenir les liens), il m'a fallu donc chercher ailleurs. Je l'ai trouvée sur ftp://alpha.gnu.org, dans le répertoire /pub/sed. J'ai téléchargé avec joie cette nouvelle version, l'ai installée, pour me rendre compte quelques minutes plus tard que la version de Sed la plus récente était la 3.02.80, que vous pouvez trouver à côté de la 3.02a, sur ftp://alpha.gnu.org. Après avoir installé GNU sed 3.02.80, j'étais prêt à faire mes expérimentations.

Le bon Sed

Dans cette série d'articles, nous utiliserons GNU sed 3.02.80. Quelques-uns (mais très peu) des exemples les plus avancés que vous trouverez plus loin dans ces articles ne fonctionnent pas avec GNU sed 3.02 ou 3.02a. Si vous utilisez une version de Sed non GNU, le résultat peut varier. Pourquoi donc ne pas prendre le temps d'installer GNU sed 3.02.80 dès maintenant ? Vous serez alors non seulement prêt pour la suite des articles, mais vous pourrez également vous vanter d'avoir la meilleure version de Sed qui existe !

Sed par l'exemple

Sed fonctionne en effectuant toutes les opérations d'édition (des « commandes ») spécifiées par l'utilisateur sur la ligne de commande. Sed est un de ces outils qui ne traitent qu'une ligne à la fois. Ainsi, les commandes seront appliquées sur chaque ligne, dans l'ordre. Il écrit le résultat sur la sortie standard (stdout) puis passe à la ligne suivante. Aucun fichier envoyé en entrée n'est modifié.

Jetons un œil à quelques exemples. Les premiers seront un peu étranges parce que je les utiliserai pour montrer comment fonctionne Sed plus que pour effectuer une manipulation quelconque. Cela dit, si vous utilisez Sed pour la première fois, il est très important que vous compreniez ces exemples. Voici le premier d'entre eux :

Exemple de code 1.1 : Exemple d'utilisation de Sed

$ sed -e 'd' /etc/services

En tapant cette commande, vous n'obtiendrez absolument aucun message de sortie. Bien, mais alors que se passe-t-il ? Dans cet exemple, nous exécutons Sed avec une commande d'édition, d. Sed ouvre le fichier /etc/services, lit une ligne dans son tampon d'édition, effectue notre commande d'édition (« supprimer la ligne »), puis affiche le tampon (qui est vide). Il répète la même étape pour chaque ligne du fichier. Vous n'obtiendrez aucun message de sortie, puisque la commande d supprime toutes les lignes du tampon d'édition !

Vous devez remarquer un certain nombre d'éléments dans cet exemple. Tout d'abord, /etc/services n'a pas du tout été modifié. Cela est dû au fait que Sed ne fait que lire le fichier spécifié dans la ligne de commande en ne l'utilisant que comme flux d'entrée. Il n'essaye pas de modifier ce fichier. Ensuite, vous remarquerez que Sed travaille en mode ligne par ligne. La commande d n'indique pas simplement à Sed de supprimer toutes les données d'un seul coup. À la place, Sed récupère l'une après l'autre les lignes de ce fichier dans un tampon d'édition interne. Une fois qu'une ligne est mise dans le tampon d'édition, Sed exécute la commande d sur ce tampon et renvoie en sortie standard le résultat (dans notre exemple : rien, vu que le contenu est supprimé). Plus tard, je vous montrerai comment utiliser des intervalles d'adresses pour contrôler quelles lignes doivent être éditées par la commande. Si aucune adresse n'est précisée, la commande sera appliquée à toutes les lignes.

La troisième chose à remarquer est l'utilisation des apostrophes autour de la commande d. Il est bon de prendre l'habitude d'utiliser des apostrophes autour des commandes Sed pour que votre console Shell ne l'interprète pas.

Sed par l'exemple, deuxième exemple

Voici un exemple d'utilisation de Sed permettant de supprimer la première ligne de /etc/services dans le flux de sortie :

Exemple de code 1.2 : Autre exemple de Sed

$ sed -e '1d' /etc/services | more

Comme vous pouvez le voir, cette commande ressemble vraiment à la première commande d, sauf que nous l'avons fait précéder d'un 1. Comme vous l'aurez probablement deviné, le 1 indique une référence à la première ligne. Contrairement au premier exemple, nous précédons le d d'une adresse numérique optionnelle. En utilisant les adresses, vous pouvez indiquer à Sed de n'effectuer les commandes que sur certaines lignes en particulier.

Intervalles d'adresses

Maintenant, intéressons-nous à spécifier un intervalle d'adresses. Dans cet exemple, Sed va supprimer les lignes de 1 à 10 dans la sortie :

Exemple de code 1.3 : Spécifier un intervalle d'adresses

$ sed -e '1,10d' /etc/services | more

Lorsque vous séparez deux adresses par une virgule, Sed va appliquer la commande suivante à l'intervalle d'adresses compris entre la première et la seconde adresse. Dans cet exemple, la commande d sera appliquée aux lignes de 1 à 10 incluses. Toutes les autres lignes seront ignorées.

Des adresses avec expressions régulières

Note : N.d.T : Pour traduire « regular expression », nous utilisons ici le terme « expression régulière », plus répandu que le terme plus conventionnel « expression rationnelle ».

Il est maintenant temps de montrer des exemples utiles. Disons que vous souhaitez voir le contenu du fichier /etc/services à l'exception des commentaires. Comme vous le savez, vous pouvez placer des commentaires dans votre fichier /etc/services en faisant commencer la ligne par un dièse « # ». Pour éviter d'afficher les commentaires, nous allons supprimer les lignes commençant par un dièse. Voici comment faire :

Exemple de code 1.4 : Supprimer les lignes commençant par un #

$ sed -e '/^#/d' /etc/services | more

Essayez cet exemple et regardez ce qui se passe. Vous remarquerez que Sed effectue sa tâche avec brio. Essayons de comprendre ce qui s'est passé.

Pour comprendre la commande « /^#/d », nous devons tout d'abord la disséquer. Laissons de côté le d (nous utilisons la même commande de suppression que précédemment). La partie nouvelle, ici, est /^#/ qui est une adresse par expression régulière. Les adresses avec des expressions régulières sont toujours encadrées par des /. Elles définissent un modèle et la commande qui suit immédiatement l'expression régulière ne sera appliquée que dans le cas où le texte vérifie les conditions spécifiées dans le modèle indiqué.

Donc, /^#/ est une expression régulière. Mais que fait-elle ? À l'évidence, c'est le bon moment pour se rafraîchir la mémoire à propos des expressions régulières.

Petit topo sur les expressions régulières

Nous pouvons utiliser les expressions régulières pour indiquer un modèle que nous souhaiterions rencontrer dans un texte. Si vous avez déjà utilisé le caractère * dans une ligne de commande Shell, vous avez déjà utilisé quelque chose qui est similaire (bien que pas identique) aux expressions régulières. Voici les caractères spéciaux que vous pouvez utiliser dans les expressions régulières :

Caractère Description
^ Indique un début de ligne.
$ Indique une fin de ligne.
. Indique n'importe quel caractère seul.
* Indique zéro ou plus occurrences du caractère précédent le *.
[ ] Indique l'occurrence d'un des caractères présents dans les [ ].

Le meilleur moyen de se faire la main avec les expressions régulières est de voir quelques exemples. Tous ces exemples seront acceptés par Sed en tant qu'adresses pouvant être placées à gauche d'une commande. En voici quelques-uns :

Expression régulière Description
/./ Récupère toutes les lignes contenant au moins un caractère.
/../ Récupère toutes les lignes contenant au moins deux caractères.
/^#/ Récupère toutes les lignes commençant par un #.
/^$/ Récupère toutes les lignes vides.
/}$/ Récupère toutes les lignes finissant par un }.
/} *$/ Récupère toutes les lignes finissant par un } suivi ou non d'espaces.
/[abc]/ Récupère toutes les lignes contenant un des caractères a, b ou c.
/^[abc]/ Récupère toutes les lignes commençant soit par un a, soit un b, soit un c.

Je vous encourage d'essayer plusieurs de ces exemples. Prenez votre temps pour vous familiariser avec les expressions régulières et pour essayer de nouvelles expressions régulières faites maison. Vous pouvez utiliser une expression régulière (ou regexp) de cette manière :

Exemple de code 1.5 : Méthode d'utilisation des regexp

$ sed -e '/regexp/d' /chemin/d/acces/de/mon/fichier | more

Sed supprimera toutes les lignes respectant les règles de la regexp. Il est cependant plus facile de s'habituer à l'usage des expressions régulières en indiquant à Sed d'afficher les regexp qui sont vérifiées et de supprimer celles qui ne correspondent pas, plutôt que l'inverse. Cela peut se faire avec la commande suivante :

Exemple de code 1.6 : Afficher les expressions correspondant à une regexp

$ sed -n -e '/regexp/p' /chemin/d/acces/de/mon/fichier | more

Remarquez la nouvelle option -n qui indique à Sed de n'afficher que les modèles de texte demandés en commande. Vous noterez également que nous avons remplacé la commande d par la commande p qui, comme vous l'aurez probablement compris, demande explicitement à Sed d'afficher les lignes reconnues par le modèle en question. Voilà. Maintenant, seules les lignes reconnues par l'expression régulière seront affichées.

Plus loin avec les adresses

Jusqu'à maintenant, nous avons jeté un œil sur les adresses pour les lignes, les intervalles d'adresses de lignes et les adresses par expression régulière, mais il existe encore d'autres possibilités. On peut spécifier deux expressions régulières séparées par une virgule et Sed reconnaîtra toutes les lignes depuis la première ligne reconnue par la première expression régulière jusqu'à la première ligne (incluse) reconnue par la seconde expression régulière. Par exemple, la commande suivante affichera un bloc de texte commençant par une ligne contenant « BEGIN » et terminant par une ligne contenant « END » :

Exemple de code 1.7 : Affichage du bloc de texte souhaité

$ sed -n -e '/BEGIN/,/END/p' /mon/fichier/texte | more

Si le mot « BEGIN » n'a pas été trouvé, rien ne sera affiché. De plus, si « BEGIN » a été trouvé, mais que « END » n'a pas été trouvé plus loin, toutes les lignes suivant le « BEGIN » seront affichées. Cela est dû au fait que Sed est un éditeur de flux et donc il ne peut pas deviner à l'avance si « END » sera ou non rencontré.

Exemple de traitement d'un code source en C

Si vous souhaitez n'afficher que la fonction main() d'un code source écrit en C, vous pouvez écrire :

Exemple de code 1.8 : Affichage de la fonction main() d'un code en C

$ sed -n -e '/main[[:space:]]*(/,/^}/p' fichiersource.c | more

Cette commande est composée de deux expressions régulières, /main[[:space:]]*(/ et /^}/, suivies d'une commande, p. La première expression régulière reconnaît la chaîne de caractère « main » suivie de zéro ou plusieurs espaces ou tabulations, suivies d'une parenthèse ouverte. Cela devrait reconnaître le début de votre fonction main() écrite en ANSI C.

Dans ce cas particulier d'expression régulière, nous rencontrons la classe de caractères « [[:space:]] ». Il s'agit d'un mot-clef spécial qui indique à Sed de reconnaître soit une tabulation, soit une espace. Si vous le souhaitez, au lieu d'écrire « [[:space:]] », vous pouvez écrire « [ » suivi d'un caractère espace littéral, puis un Ctrl-V, une tabulation littérale et enfin un « ] » (la commande Ctrl-V indique à bash que vous souhaitez insérer une vraie tabulation plutôt qu'une complétion de commande). Il est cependant plus lisible d'utiliser la classe de caractères « [[:space:]] ».

Bon, passons maintenant à la seconde regexp. /^{/ reconnaîtra un caractère « } » en début de ligne. Si votre code est correctement formaté, il reconnaîtra alors le crochet fermant de votre fonction main(). Si ce n'est pas le cas, cela n'affichera pas le code souhaité. C'est un point important à noter lors de la reconnaissance de modèles.

La commande p fait ce qu'elle a toujours fait : indiquer de manière explicite à Sed d'afficher les lignes souhaitées, en conjonction avec le mode silencieux -n que nous utilisons. Essayez de lancer la commande sur un code source écrit en C, Sed devrait alors afficher le bloc correspondant à la fonction main(), en incluant les lignes « main() » et « } ».

Pour la suite

Maintenant que nous avons vu les bases, nous sommes prêts à passer aux deux prochains articles. Si vous êtes avides de commandes Sed, soyez patient, elles arrivent ! En attendant, vous pouvez jeter un œil sur les ressources suivantes traitant de Sed et des expressions régulières.

2.  Ressources

Liens utiles



Imprimer

Dernière mise à jour le 14 octobre 2010

Une version originale plus récente datée du 2 janvier 2012 existe.

Résumé : Dans cette série d'articles, Daniel Robbins vous montrera comment utiliser Sed, un éditeur de flux UNIX très puissant (mais souvent méconnu). Sed est l'outil idéal pour éditer un groupe de fichiers ou pour créer des scripts Shell qui modifient des fichiers existants de manière efficace.

Daniel Robbins
Auteur

Clément Varaldi
Traducteur

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.