- Dave McKay
@TheGurkha
- Le 16 avril 2020, 8 :00am EDT
Cela peut paraître fou, mais la commande Linux sed
est un éditeur de texte sans interface. Vous pouvez l’utiliser depuis la ligne de commande pour manipuler le texte dans les fichiers et les flux. Nous allons vous montrer comment exploiter sa puissance.
La puissance de sed
La sed
commande est un peu comme les échecs : il faut une heure pour apprendre les bases et une vie entière pour les maîtriser (ou, du moins, beaucoup de pratique). Nous allons vous montrer une sélection de gambits d’ouverture dans chacune des grandes catégories de sed
fonctionnalités.
sed
est un éditeur de flux qui fonctionne sur des entrées en pipeline ou des fichiers de texte. Il ne dispose cependant pas d’une interface interactive d’éditeur de texte. Vous lui fournissez plutôt des instructions qu’il doit suivre pendant qu’il travaille sur le texte. Tout cela fonctionne dans Bash et d’autres shells de ligne de commande.
Avec sed
, vous pouvez faire tout ce qui suit :
- Sélectionner du texte
- Substituer du texte
- Ajouter des lignes au texte
- Supprimer des lignes du texte
- Modifier (ou préserver) un fichier original
Nous avons structuré nos exemples pour introduire et démontrer des concepts, et non pour produire les commandes les plus ters (et les moins abordables) sed
. Cependant, les fonctionnalités de filtrage et de sélection de texte de sed
reposent en grande partie sur les expressions régulières (regex). Vous allez devoir vous familiariser avec celles-ci pour tirer le meilleur parti de sed
.
RELATED : Comment utiliser les expressions régulières (regex) sous Linux
Un exemple simple
Pour commencer, nous allons utiliser echo
pour envoyer du texte à sed
à travers un tuyau, et faire en sorte que sed
substitue une partie du texte. Pour ce faire, nous tapons ce qui suit :
echo howtogonk | sed 's/gonk/geek/'
La commande echo
envoie « howtogonk » dans sed
, et notre règle de substitution simple (le « s » signifie substitution) est appliquée. sed
recherche dans le texte d’entrée une occurrence de la première chaîne, et remplacera toute correspondance par la seconde.
La chaîne « gonk » est remplacée par « geek », et la nouvelle chaîne est imprimée dans la fenêtre du terminal.
Les substitutions sont probablement l’utilisation la plus courante de sed
. Mais avant de pouvoir plonger plus profondément dans les substitutions, nous devons savoir comment sélectionner et faire correspondre du texte.
Sélectionner du texte
Nous allons avoir besoin d’un fichier texte pour nos exemples. Nous en utiliserons un qui contient une sélection de vers du poème épique » The Rime of the Ancient Mariner » de Samuel Taylor Coleridge. »
Nous tapons ce qui suit pour en prendre connaissance avec less
:
less coleridge.txt
Pour sélectionner certaines lignes du fichier, nous fournissons les lignes de début et de fin de la plage que nous voulons sélectionner. Un seul chiffre sélectionne cette ligne.
Pour extraire les lignes un à quatre, on tape cette commande :
sed -n '1,4p' coleridge.txt
Notez la virgule entre 1
et 4
. Le p
signifie « imprimer les lignes appariées ». Par défaut, sed
imprime toutes les lignes. Nous verrions tout le texte du fichier avec les lignes correspondantes imprimées deux fois. Pour éviter cela, nous utiliserons l’option -n
(quiet) pour supprimer le texte non apparié.
Nous changeons les numéros de ligne afin de pouvoir sélectionner un verset différent, comme indiqué ci-dessous :
sed -n '6,9p' coleridge.txt
Nous pouvons utiliser l’option -e
(expression) pour effectuer des sélections multiples. Avec deux expressions, nous pouvons sélectionner deux versets, comme suit :
sed -n -e '1,4p' -e '31,34p' coleridge.txt
Si nous réduisons le premier chiffre de la deuxième expression, nous pouvons insérer un blanc entre les deux versets. On tape ce qui suit :
sed -n -e '1,4p' -e '30,34p' coleridge.txt
Nous pouvons également choisir une ligne de départ et dire à sed
d’avancer dans le fichier et d’imprimer une ligne sur deux, une ligne sur cinq, ou de sauter un nombre quelconque de lignes. La commande est similaire à celles que nous avons utilisées ci-dessus pour sélectionner une plage. Cette fois, cependant, nous utiliserons un tilde (~
) au lieu d’une virgule pour séparer les numéros.
Le premier numéro indique la ligne de départ. Le deuxième nombre indique sed
quelles lignes après la ligne de départ nous voulons voir. Le nombre 2 signifie chaque deuxième ligne, 3 signifie chaque troisième ligne, et ainsi de suite.
Nous tapons ce qui suit :
sed -n '1~2p' coleridge.txt
Vous ne saurez pas toujours où se trouve le texte que vous recherchez dans le fichier, ce qui signifie que les numéros de ligne ne seront pas toujours d’une grande aide. Cependant, vous pouvez également utiliser sed
pour sélectionner les lignes qui contiennent des motifs de texte correspondants. Par exemple, extrayons toutes les lignes qui commencent par « Et ».
Le signe d’insertion (^
) représente le début de la ligne. Nous entourons notre terme de recherche de barres obliques (/
). Nous incluons également un espace après « And » pour que des mots comme « Android » ne soient pas inclus dans le résultat.
La lecture des scripts sed
peut être un peu difficile au début. Le /p
signifie » imprimer « , tout comme dans les commandes que nous avons utilisées ci-dessus. Dans la commande suivante, cependant, une barre oblique le précède :
sed -n '/^And /p' coleridge.txt
Trois lignes qui commencent par « And » sont extraites du fichier et affichées pour nous.
Faire des substitutions
Dans notre premier exemple, nous vous avons montré le format de base suivant pour une sed
substitution :
echo howtogonk | sed 's/gonk/geek/'
La s
indique à sed
qu’il s’agit d’une substitution. La première chaîne est le motif de recherche, et la seconde est le texte avec lequel nous voulons remplacer ce texte apparié. Bien sûr, comme pour tout ce qui concerne Linux, le diable se cache dans les détails.
Nous tapons ce qui suit pour changer toutes les occurrences de « jour » en « semaine », et donner au marin et à l’albatros plus de temps pour se lier:
sed -n 's/day/week/p' coleridge.txt
Dans la première ligne, seule la deuxième occurrence de « jour » est modifiée. Cela est dû au fait que sed
s’arrête après la première correspondance par ligne. Nous devons ajouter un « g » à la fin de l’expression, comme indiqué ci-dessous, pour effectuer une recherche globale afin que toutes les correspondances de chaque ligne soient traitées :
sed -n 's/day/week/gp' coleridge.txt
Ceci correspond à trois des quatre occurrences de la première ligne. Comme le premier mot est « Day », et que sed
est sensible à la casse, il ne considère pas que cette instance est la même que « day ». »
Nous tapons ce qui suit, en ajoutant un i
à la commande à la fin de l’expression pour indiquer l’insensibilité à la casse:
sed -n 's/day/week/gip' coleridge.txt
Cela fonctionne, mais vous ne voudrez pas toujours activer l’insensibilité à la casse pour tout. Dans ces cas, vous pouvez utiliser un groupe regex pour ajouter une insensibilité à la casse spécifique au motif.
Par exemple, si nous enfermons des caractères entre crochets (), ils sont interprétés comme « tout caractère de cette liste de caractères. »
Nous tapons ce qui suit, et nous incluons « D » et « d » dans le groupe, pour nous assurer qu’il correspond à la fois à « Day » et à « day »:
sed -n 's/ay/week/gp' coleridge.txt
Nous pouvons également restreindre les substitutions à des sections du fichier. Disons que notre fichier contient un espacement bizarre dans le premier vers. Nous pouvons utiliser la commande familière suivante pour voir le premier couplet:
sed -n '1,4p' coleridge.txt
Nous allons rechercher deux espaces et les remplacer par un seul. Nous le ferons globalement pour que l’action soit répétée sur toute la ligne. Pour être clair, le motif de recherche est espace, espace astérisque (*
), et la chaîne de substitution est un seul espace. Le 1,4
restreint la substitution aux quatre premières lignes du fichier.
Nous mettons tout cela ensemble dans la commande suivante :
sed -n '1,4 s/ */ /gp' coleridge.txt
Cela fonctionne bien ! Le motif de recherche est ce qui est important ici. L’astérisque (*
) représente zéro ou plus du caractère précédent, qui est un espace. Ainsi, le motif de recherche recherche des chaînes de caractères d’un espace ou plus.
Si nous substituons un espace unique à toute séquence d’espaces multiples, nous rendrons au fichier un espacement régulier, avec un espace unique entre chaque mot. Cela substituera également un espace unique pour un espace unique dans certains cas, mais cela n’affectera rien de façon négative – nous obtiendrons toujours notre résultat souhaité.
Si nous tapons ce qui suit et réduisons le motif de recherche à un seul espace, vous verrez immédiatement pourquoi nous devons inclure deux espaces:
sed -n '1,4 s/ */ /gp' coleridge.txt
Parce que l’astérisque correspond à zéro ou plus du caractère précédent, il voit chaque caractère qui n’est pas un espace comme un « espace zéro » et lui applique la substitution.
Cependant, si nous incluons deux espaces dans le motif de recherche, sed
doit trouver au moins un caractère espace avant d’appliquer la substitution. Cela garantit que les caractères qui ne sont pas des espaces ne seront pas touchés.
Nous tapons ce qui suit, en utilisant la -e
(expression) que nous avons utilisée précédemment, qui nous permet d’effectuer deux substitutions ou plus simultanément :
sed -n -e 's/motion/flutter/gip' -e 's/ocean/gutter/gip' coleridge.txt
Nous pouvons obtenir le même résultat si nous utilisons un point-virgule (;
) pour séparer les deux expressions, comme suit :
sed -n 's/motion/flutter/gip;s/ocean/gutter/gip' coleridge.txt
Lorsque nous avons échangé « day » contre « week » dans la commande suivante, l’instance de « day » dans l’expression « well a-day » a également été échangée :
sed -n 's/ay/week/gp' coleridge.txt
Pour éviter cela, nous ne pouvons tenter des substitutions que sur les lignes qui correspondent à un autre motif. Si nous modifions la commande pour avoir un motif de recherche au début, nous n’envisagerons d’opérer que sur les lignes qui correspondent à ce motif.
Nous tapons ce qui suit pour que notre motif de correspondance soit le mot » after » :
sed -n '/after/ s/ay/week/gp' coleridge.txt
Cela nous donne la réponse que nous voulons.
Substitutions plus complexes
Donnons une pause à Coleridge et utilisons sed
pour extraire les noms du fichier etc/passwd
.
Il existe des façons plus courtes de le faire (nous y reviendrons plus tard), mais nous utiliserons ici la façon plus longue pour démontrer un autre concept. Chaque élément apparié dans un motif de recherche (appelé sous-expressions) peut être numéroté (jusqu’à un maximum de neuf éléments). Vous pouvez ensuite utiliser ces numéros dans vos commandes sed
pour faire référence à des sous-expressions spécifiques.
Vous devez mettre la sous-expression entre parenthèses pour que cela fonctionne. Les parenthèses doivent également être précédées d’une barre oblique inversée (\
) pour éviter qu’elles soient traitées comme un caractère normal.
Pour ce faire, vous devez taper ce qui suit :
sed 's/\(*\).*/\1/' /etc/passwd
Décomposons cela :
-
sed 's/
: La commandesed
et le début de l’expression de substitution. -
\(
: La parenthèse ouvrante entourant la sous-expression, précédée d’une barre oblique inverse (\
). -
*
: La première sous-expression du terme de recherche contient un groupe entre crochets. Le signe d’insertion (^
) signifie « pas » lorsqu’il est utilisé dans un groupe. Un groupe signifie que tout caractère qui n’est pas un deux-points (:
) sera accepté comme correspondance. -
\)
: La parenthèse fermante avec une barre oblique inverse précédente (\
). -
.*
: Cette deuxième sous-expression de recherche signifie « tout caractère et n’importe quel nombre d’entre eux. » -
/\1
: La partie substitution de l’expression contient1
précédée d’une barre oblique inverse (\
). Cela représente le texte qui correspond à la première sous-expression. -
/'
: La barre oblique de fermeture (/
) et le guillemet simple ('
) terminent la commandesed
.
Ce que tout cela signifie, c’est que nous allons chercher toute chaîne de caractères qui ne contient pas de deux-points (:
), qui sera la première instance de texte correspondant. Ensuite, nous recherchons tout ce qui se trouve sur cette ligne, ce qui sera la deuxième instance du texte correspondant. Nous allons remplacer la ligne entière par le texte qui correspondait à la première sous-expression.
Chaque ligne du fichier /etc/passwd
commence par un nom d’utilisateur terminé par deux points. Nous faisons correspondre tout jusqu’au premier deux-points, puis nous substituons cette valeur à la ligne entière. Ainsi, nous avons isolé les noms d’utilisateur.
Suivant, nous allons mettre la deuxième sous-expression entre parenthèses afin de pouvoir la référencer par numéro, également. Nous allons également remplacer \1
par \2
. Notre commande va maintenant substituer à la ligne entière tout ce qui se trouve entre les premiers deux-points (:
) et la fin de la ligne.
Nous tapons ce qui suit :
sed 's/\(*\)\(.*\)/\2/' /etc/passwd
Ces petits changements inversent le sens de la commande, et nous obtenons tout sauf les noms d’utilisateurs.
Maintenant, jetons un coup d’œil à la façon rapide et facile de faire cela.
Notre terme de recherche va du premier deux-points (:
) à la fin de la ligne. Comme notre expression de substitution est vide (//
), nous ne remplacerons pas le texte apparié par quoi que ce soit.
Donc, nous tapons ce qui suit, en hachant tout ce qui se trouve entre les premiers deux-points (:
) et la fin de la ligne, ne laissant que les noms d’utilisateur :
sed 's/:.*//" /etc/passwd
Voyons un exemple dans lequel nous référençons la première et la deuxième correspondance dans la même commande.
Nous avons un fichier de virgules (,
) séparant les noms et prénoms. Nous voulons les lister comme « nom de famille, prénom ». Nous pouvons utiliser cat
, comme indiqué ci-dessous, pour voir ce que contient le fichier :
cat geeks.txt
Comme beaucoup de commandes sed
, la suivante peut sembler impénétrable au début :
sed 's/^\(.*\),\(.*\)$/\2,\1 /g' geeks.txt
C’est une commande de substitution comme les autres que nous avons utilisées, et le motif de recherche est assez facile. Nous allons le décomposer ci-dessous :
-
sed 's/
: La commande de substitution normale. -
^
: Comme le signe d’insertion n’est pas dans un groupe (), cela signifie « Le début de la ligne. »
-
\(.*\),
: La première sous-expression est un nombre quelconque de caractères quelconques. Elle est entourée de parenthèses , dont chacune est précédée d’une barre oblique inverse (\
) afin que nous puissions la référencer par numéro. L’ensemble de notre motif de recherche jusqu’à présent se traduit par une recherche du début de la ligne jusqu’à la première virgule (,
) pour tout nombre de caractères quelconques. -
\(.*\)
: La sous-expression suivante est (encore) tout nombre de caractères quelconques. Elle est également placée entre parenthèses , toutes deux précédées d’une barre oblique inverse (\
) afin que nous puissions référencer le texte correspondant par numéro. -
$/
: Le signe dollar ($
) représente la fin de la ligne et permettra à notre recherche de se poursuivre jusqu’à la fin de la ligne. Nous l’avons utilisé simplement pour introduire le signe du dollar. Nous n’en avons pas vraiment besoin ici, car l’astérisque (*
) irait jusqu’à la fin de la ligne dans ce scénario. La barre oblique (/
) complète la section du modèle de recherche. -
\2,\1 /g'
: Comme nous avons mis nos deux sous-expressions entre parenthèses, nous pouvons nous référer aux deux par leur numéro. Comme nous voulons inverser l’ordre, nous les tapons sous la formesecond-match,first-match
. Les numéros doivent être précédés d’une barre oblique inverse (\
). -
/g
: Cela permet à notre commande de fonctionner globalement sur chaque ligne. -
geeks.txt
: Le fichier sur lequel nous travaillons.
Vous pouvez également utiliser la commande Cut (c
) pour substituer des lignes entières qui correspondent à votre modèle de recherche. Nous tapons ce qui suit pour rechercher une ligne contenant le mot » neck » et la remplacer par une nouvelle chaîne de texte :
sed '/neck/c Around my wrist was strung' coleridge.txt
Notre nouvelle ligne apparaît maintenant au bas de notre extrait.
Insertion de lignes et de texte
Nous pouvons également insérer de nouvelles lignes et du texte dans notre fichier. Pour insérer de nouvelles lignes après toute ligne correspondante, nous utiliserons la commande Append (a
).
Voici le fichier avec lequel nous allons travailler :
cat geeks.txt
Nous avons numéroté les lignes pour que ce soit un peu plus facile à suivre.
Nous tapons ce qui suit pour rechercher les lignes qui contiennent le mot » He « , et insérer une nouvelle ligne sous celles-ci :
sed '/He/a --> Inserted!' geeks.txt
Nous tapons ce qui suit et incluons la commande Insert (i
) pour insérer la nouvelle ligne au-dessus de celles qui contiennent du texte correspondant:
sed '/He/i --> Inserted!' geeks.txt
Nous pouvons utiliser l’esperluette (&
), qui représente le texte original apparié, pour ajouter un nouveau texte à une ligne appariée. \1
\2
, et ainsi de suite, représentent des sous-expressions correspondantes.
Pour ajouter du texte au début d’une ligne, nous utiliserons une commande de substitution qui correspond à tout ce qui se trouve sur la ligne, combinée à une clause de remplacement qui combine notre nouveau texte avec la ligne originale.
Pour faire tout cela, nous tapons ce qui suit :
sed 's/.*/--> Inserted &/' geeks.txt
Nous tapons ce qui suit, y compris la commande G
, qui ajoutera une ligne blanche entre chaque ligne:
sed 'G' geeks.txt
Si vous voulez ajouter deux lignes vides ou plus, vous pouvez utiliser G;G
G;G;G
, et ainsi de suite.
Suppression de lignes
La commande Supprimer (d
) supprime les lignes qui correspondent à un motif de recherche, ou celles spécifiées avec des numéros de ligne ou des plages.
Par exemple, pour supprimer la troisième ligne, nous devons taper ce qui suit :
sed '3d' geeks.txt
Pour supprimer la plage des lignes quatre à cinq, nous devons taper ce qui suit :
sed '4,5d' geeks.txt
Pour supprimer les lignes en dehors d’une plage, nous utilisons un point d’exclamation (!
), comme indiqué ci-dessous :
sed '6,7!d' geeks.txt
Sauvegarder vos changements
Jusqu’à présent, tous nos résultats se sont imprimés dans la fenêtre de terminal, mais nous ne les avons encore sauvegardés nulle part. Pour les rendre permanents, vous pouvez soit écrire vos modifications dans le fichier d’origine, soit les rediriger vers un nouveau fichier.
La surécriture de votre fichier d’origine nécessite une certaine prudence. Si votre sed
commande est erronée, vous pourriez apporter au fichier d’origine des modifications difficiles à annuler.
Pour une certaine tranquillité d’esprit, sed
peut créer une sauvegarde du fichier d’origine avant d’exécuter sa commande.
Vous pouvez utiliser l’option In-place (-i
) pour indiquer à sed
d’écrire les modifications dans le fichier original, mais si vous y ajoutez une extension de fichier, sed
sauvegardera le fichier original dans un nouveau fichier. Il aura le même nom que le fichier original, mais avec une nouvelle extension de fichier.
Pour faire une démonstration, nous allons rechercher toutes les lignes qui contiennent le mot « He » et les supprimer. Nous allons également sauvegarder notre fichier original vers un nouveau fichier en utilisant l’extension BAK.
Pour faire tout cela, nous tapons ce qui suit :
sed -i'.bak' '/^.*He.*$/d' geeks.txt
Nous tapons ce qui suit pour nous assurer que notre fichier de sauvegarde est inchangé :
cat geeks.txt.bak
Nous pouvons également taper ce qui suit pour rediriger la sortie vers un nouveau fichier et obtenir un résultat similaire :
sed -i'.bak' '/^.*He.*$/d' geeks.txt > new_geeks.txt
Nous utilisons cat
pour confirmer que les modifications ont été écrites dans le nouveau fichier, comme indiqué ci-dessous :
cat new_geeks.txt
Ayant sed tout ça
Comme vous l’avez probablement remarqué, même ce rapide abécédaire de sed
est assez long. Il y a beaucoup de choses dans cette commande, et il y a encore plus de choses que vous pouvez faire avec elle.
Espérons cependant que ces concepts de base vous aient fourni une base solide sur laquelle vous pourrez vous appuyer pour continuer à en apprendre davantage.
Dave McKay a d’abord utilisé des ordinateurs lorsque le ruban de papier perforé était en vogue, et il n’a jamais cessé de programmer depuis. Après plus de 30 ans dans l’industrie informatique, il est maintenant un journaliste technologique à plein temps. Au cours de sa carrière, il a travaillé comme programmeur indépendant, responsable d’une équipe internationale de développement de logiciels, chef de projet de services informatiques et, plus récemment, comme responsable de la protection des données. Dave est un évangéliste Linux et un défenseur de l’open source.Lire la bio complète »