Comment utiliser la commande sed sur Linux
Cela peut sembler fou, mais le Linux sed
est un éditeur de texte sans interface. Vous pouvez l'utiliser à partir de la ligne de commande pour manipuler du texte dans des fichiers et des flux. Nous allons vous montrer comment exploiter sa puissance.
La puissance de sed
le sed
la commande est un peu comme les échecs: il faut une heure pour apprendre les bases et toute une vie pour les maîtriser (ou, au moins, beaucoup de pratique). Nous allons vous montrer une sélection de gambits d'ouverture dans chacune des principales catégories de sed
Fonctionnalité.
sed
est un éditeur de flux qui fonctionne sur une entrée canalisée ou des fichiers de texte. Cependant, il ne dispose pas d'une interface d'édition de texte interactive. Au lieu de cela, vous fournissez des instructions à suivre pendant qu'il fonctionne dans le texte. Tout cela fonctionne dans Bash et d'autres shells de ligne de commande.
Avec sed
vous pouvez effectuer toutes les opérations suivantes:
- Sélectionnez le texte
- Texte de remplacement
- Ajouter des lignes au texte
- Supprimer des lignes du texte
- Modifier (ou conserver) un fichier d'origine
Nous avons structuré nos exemples pour introduire et démontrer des concepts, pas pour produire le plus simple (et le moins accessible) sed
commandes. Cependant, les fonctionnalités de filtrage et de sélection de texte de sed
s'appuyer fortement sur les expressions régulières (expressions régulières). Vous allez avoir besoin de vous familiariser avec ceux-ci pour tirer le meilleur parti de sed
.
Un exemple simple
Tout d'abord, nous allons utiliser echo
envoyer du texte à sed
à travers un tuyau, et ont sed
remplacer une partie du texte. Pour ce faire, nous tapons ce qui suit:
echo howtogonk | sed 's/gonk/geek/'
le echo
commande envoie "howtogonk" dans sed
et notre règle de substitution simple (le «s» signifie substitution) est appliquée. sed
recherche une occurrence de la première chaîne dans le texte d'entrée et remplace toutes les correspondances 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
. Avant de pouvoir approfondir les substitutions, nous devons cependant savoir comment sélectionner et faire correspondre le texte.
Sélection de 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 de Samuel Taylor Coleridge «Le Rime de l'ancien marin».
Nous tapons ce qui suit pour y jeter un œil 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 numéro sélectionne cette ligne.
Pour extraire les lignes un à quatre, nous tapons cette commande:
sed -n '1,4p' coleridge.txt
Notez la virgule entre 1
et 4
. le p
signifie «imprimer les lignes correspondantes». 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 le -n
(silencieux) option pour supprimer le texte inégalé.
Nous modifions 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 le -e
(expression) option pour effectuer plusieurs sélections. Avec deux expressions, nous pouvons sélectionner deux versets, comme ceci:
sed -n -e '1,4p' -e '31,34p' coleridge.txt
Si nous réduisons le premier nombre dans la deuxième expression, nous pouvons insérer un blanc entre les deux versets. Nous tapons 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
pour parcourir le fichier et imprimer des lignes alternatives, toutes les cinq lignes, ou pour 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 nombres.
Le premier chiffre indique la ligne de départ. Le deuxième chiffre indique sed
quelles lignes après la ligne de départ nous voulons voir. Le nombre 2 signifie toutes les deux lignes, 3 signifie toutes les trois lignes, 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 des lignes contenant des motifs de texte correspondants. Par exemple, extrayons toutes les lignes commençant par "Et".
Le caret (^
) représente le début de la ligne. Nous allons inclure notre terme de recherche dans des barres obliques (/
). Nous incluons également un espace après "Et" afin que des mots comme "Android" ne soient pas inclus dans le résultat.
En train de lire sed
les scripts peuvent être un peu difficiles 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 la précède:
sed -n '/^And /p' coleridge.txt
Trois lignes commençant par «Et» 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 un sed
substitution:
echo howtogonk | sed 's/gonk/geek/'
le s
raconte sed
c'est une substitution. La première chaîne est le modèle de recherche, et la seconde est le texte avec lequel nous voulons remplacer ce texte correspondant. Bien sûr, comme pour tout ce qui concerne Linux, le diable est dans les détails.
Nous tapons ce qui suit pour changer toutes les occurrences de «jour» en «semaine» et donner plus de temps au marin et à l'albatros 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. Ceci est dû au fait sed
s'arrête après le premier match 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
Cela correspond à trois des quatre de la première ligne. Parce que le premier mot est "Jour", et sed
est sensible à la casse, il ne considère pas que cette instance est la même que "jour".
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 peut-être pas toujours activer l'insensibilité à la casse pour tout. Dans ces cas, vous pouvez utiliser un groupe d'expressions régulières pour ajouter une insensibilité à la casse spécifique au modèle.
Par exemple, si nous mettons des caractères entre crochets (()
), ils sont interprétés comme «n'importe quel caractère de cette liste de caractères».
Nous tapons ce qui suit et incluons "D" et "d" dans le groupe, pour nous assurer qu'il correspond à la fois à "Jour" et "jour":
sed -n 's/(Dd)ay/week/gp' coleridge.txt
Nous pouvons également limiter les substitutions aux sections du fichier. Disons que notre fichier contient un espacement étrange dans le premier verset. Nous pouvons utiliser la commande familière suivante pour voir le premier verset:
sed -n '1,4p' coleridge.txt
Nous allons rechercher deux espaces et les remplacer par un. Nous le ferons à l'échelle mondiale afin que l'action se répète sur toute la ligne. Pour être clair, le modèle de recherche est l'espace, l'astérisque espace (*
), et la chaîne de substitution est un espace unique. le 1,4
limite 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 modèle 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 modèle de recherche recherche des chaînes d'un espace ou plus.
Si nous substituons un seul espace à une séquence de plusieurs espaces, nous rétablirons l'espacement régulier du fichier, avec un seul espace entre chaque mot. Dans certains cas, cela remplacera également un seul espace par un seul espace, mais cela n'affectera rien, nous obtiendrons toujours le résultat souhaité.
Si nous tapons ce qui suit et réduisons le modèle de recherche à un seul espace, vous verrez immédiatement pourquoi nous devons inclure deux espaces:
sed -n '1,4 s/ */ /gp' coleridge.txt
Étant donné 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 modèle de recherche, sed
doit trouver au moins un caractère espace avant d'appliquer la substitution. Cela garantit que les personnages non spatiaux resteront intacts.
Nous tapons ce qui suit, en utilisant le -e
(expression) que nous avons utilisée précédemment, ce qui nous permet de faire 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 ceci:
sed -n 's/motion/flutter/gip;s/ocean/gutter/gip' coleridge.txt
Lorsque nous avons échangé «jour» pour «semaine» dans la commande suivante, l'instance de «jour» dans l'expression «bien un jour» a également été échangée:
sed -n 's/(Dd)ay/week/gp' coleridge.txt
Pour éviter cela, nous ne pouvons tenter des substitutions que sur des lignes qui correspondent à un autre modèle. Si nous modifions la commande pour avoir un modèle de recherche au début, nous ne considérerons que l’opération sur les lignes qui correspondent à ce modèle.
Nous tapons ce qui suit pour faire de notre modèle de correspondance le mot «après»:
sed -n '/after/ s/(Dd)ay/week/gp' coleridge.txt
Cela nous donne la réponse que nous voulons.
Substitutions plus complexes
Faisons une pause à Coleridge et utilisons sed
pour extraire des noms du etc/passwd
fichier.
Il existe des moyens plus courts de le faire (plus à ce sujet plus tard), mais nous utiliserons le moyen le plus long ici pour démontrer un autre concept. Chaque élément correspondant dans un modèle de recherche (appelé sous-expressions) peut être numéroté (jusqu'à un maximum de neuf éléments). Vous pouvez ensuite utiliser ces numéros dans votre sed
pour référencer 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 inverse () pour éviter qu'ils ne soient traités comme un personnage normal.
Pour ce faire, vous devez taper ce qui suit:
sed 's/((^:)*).*/1/' /etc/passwd
Décomposons ceci:
sed 's/
: lesed
et le début de l'expression de substitution.(
: La parenthèse d'ouverture ((
) 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 caret (^
) signifie «non» lorsqu'il est utilisé en groupe. Un groupe signifie tout personnage qui n'est pas un deux-points (:
) sera accepté comme match.)
: La parenthèse fermante ()
) avec une barre oblique inverse précédente ().
.*
: Cette deuxième sous-expression de recherche signifie «n'importe quel caractère et n'importe quel nombre»./1
: La portion de substitution de l'expression contient1
précédé d'une barre oblique inverse (). Cela représente le texte qui correspond à la première sous-expression.
/'
: La barre oblique de fermeture (/
) et guillemet simple ('
) mettre fin à lased
commander.
Cela signifie que nous allons rechercher toute chaîne de caractères ne contenant pas de deux-points (:
), qui sera la première instance de correspondance de texte. Ensuite, nous recherchons autre chose sur cette ligne, qui sera la deuxième instance de correspondance de texte. Nous allons remplacer la ligne entière par le texte correspondant à la première sous-expression.
Chaque ligne du /etc/passwd
le fichier commence par un nom d'utilisateur terminé par deux points. Nous faisons correspondre tout jusqu'au premier deux-points, puis substituons cette valeur à la ligne entière. Nous avons donc isolé les noms d'utilisateur.
Ensuite, nous allons mettre la deuxième sous-expression entre parenthèses (()
) afin que nous puissions également y faire référence par numéro. Nous remplacerons également 1
avec 2
. Notre commande va maintenant remplacer la ligne entière par tout depuis le premier deux-points (:
) jusqu'à 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'utilisateur.
Voyons maintenant la manière simple et rapide de procéder.
Notre terme de recherche provient du premier côlon (:
) jusqu'à la fin de la ligne. Parce que notre expression de substitution est vide (//
), nous ne remplacerons le texte correspondant par rien.
Donc, nous tapons ce qui suit, coupant tout du premier côlon (:
) jusqu'à la fin de la ligne, en ne laissant que les noms d'utilisateur:
sed 's/:.*//" /etc/passwd
Regardons un exemple dans lequel nous référençons les première et deuxième correspondances dans la même commande.
Nous avons un fichier de virgules (,
) séparant le prénom et le nom. Nous voulons les répertorier comme «nom, prénom». On peut utiliser cat
, comme illustré ci-dessous, pour voir le contenu du fichier:
cat geeks.txt
Comme beaucoup de sed
commandes, celle-ci pourrait sembler impénétrable au premier abord:
sed 's/^(.*),(.*)$/2,1 /g' geeks.txt
Il s'agit d'une commande de substitution comme les autres que nous avons utilisées, et le modèle de recherche est assez simple. Nous allons le détailler ci-dessous:
sed 's/
: La commande de substitution normale.^
: Parce que le curseur 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. Il est placé entre parenthèses (()
), dont chacun est précédé d'une barre oblique inverse () afin que nous puissions y faire référence par numéro. Jusqu'à présent, l'ensemble de notre modèle de recherche se traduit par une recherche depuis le début de la ligne jusqu'à la première virgule (
,
) pour n'importe quel nombre de caractères.(.*)
: La sous-expression suivante est (encore) n'importe quel nombre de n'importe quel caractère. Il est également placé entre parenthèses (()
), tous deux précédés 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 dollar. Nous n'en avons pas vraiment besoin ici, comme l'astérisque (*
) irait au bout de la ligne dans ce scénario. La barre oblique (/
) termine la section du modèle de recherche.2,1 /g'
: Parce que nous avons mis nos deux sous-expressions entre parenthèses, nous pouvons les désigner toutes les deux par leur nombre. Parce que nous voulons inverser l'ordre, nous les tapons commesecond-match,first-match
. Les chiffres 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 Couper (c
) pour remplacer des lignes entières qui correspondent à votre modèle de recherche. Nous tapons ce qui suit pour rechercher une ligne contenant le mot «cou» 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 celles qui correspondent, nous utiliserons la commande Ajouter (a
).
Voici le fichier avec lequel nous allons travailler:
cat geeks.txt
Nous avons numéroté les lignes pour rendre cela un peu plus facile à suivre.
Nous tapons ce qui suit pour rechercher les lignes qui contiennent le mot «He» et insérons une nouvelle ligne en dessous:
sed '/He/a --> Inserted!' geeks.txt
Nous tapons ce qui suit et incluons la commande d'insertion (i
) pour insérer la nouvelle ligne au-dessus de celles qui contiennent le texte correspondant:
sed '/He/i --> Inserted!' geeks.txt
Nous pouvons utiliser l'esperluette (&
), qui représente le texte correspondant d'origine, pour ajouter un nouveau texte à une ligne correspondante. 1
, 2
, et ainsi de suite, représentent des sous-expressions correspondantes.
Pour ajouter du texte au début d'une ligne, nous allons utiliser une commande de substitution qui correspond à tout sur la ligne, combinée à une clause de remplacement qui combine notre nouveau texte avec la ligne d'origine.
Pour faire tout cela, nous tapons ce qui suit:
sed 's/.*/--> Inserted &/' geeks.txt
Nous tapons ce qui suit, y compris le G
, qui ajoutera une ligne vierge entre chaque ligne:
sed 'G' geeks.txt
Si vous souhaitez ajouter deux lignes vides ou plus, vous pouvez utiliser G;G
, G;G;G
, etc.
Suppression de lignes
La commande Supprimer (d
) supprime les lignes qui correspondent à un modèle 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 tapons ce qui suit:
sed '3d' geeks.txt
Pour supprimer la plage de lignes quatre à cinq, nous tapons ce qui suit:
sed '4,5d' geeks.txt
Pour supprimer des lignes en dehors d'une plage, nous utilisons un point d'exclamation (!
), comme indiqué ci-dessous:
sed '6,7!d' geeks.txt
Sauvegarder vos modifications
Jusqu'à présent, tous nos résultats ont été imprimés dans la fenêtre du terminal, mais nous ne les avons encore enregistrés nulle part. Pour les rendre permanents, vous pouvez soit écrire vos modifications dans le fichier d'origine, soit les rediriger vers un nouveau.
Le remplacement de votre fichier d'origine nécessite une certaine prudence. Si ton sed
La commande est incorrecte, vous pouvez apporter des modifications au fichier d'origine qui sont difficiles à annuler.
Pour une tranquillité d'esprit, sed
peut créer une sauvegarde du fichier d'origine avant d'exécuter sa commande.
Vous pouvez utiliser l'option sur place (-i
) dire sed
pour écrire les modifications dans le fichier d'origine, mais si vous lui ajoutez une extension de fichier, sed
sauvegardera le fichier d'origine dans un nouveau. Il aura le même nom que le fichier d'origine, mais avec une nouvelle extension de fichier.
Pour le démontrer, nous rechercherons toutes les lignes contenant le mot "He" et les supprimerons. Nous allons également sauvegarder notre fichier d'origine dans un nouveau 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 séduit tout ça
Comme vous l’avez probablement remarqué, même cette introduction rapide sed
est assez long. Il y a beaucoup à faire avec cette commande, et vous pouvez faire encore plus avec.
Nous espérons cependant que ces concepts de base ont fourni une base solide sur laquelle vous pouvez vous baser pour continuer à en apprendre davantage.