GNU/Linux >> Tutoriels Linux >  >> Linux

Le concept de 'Hold space' et 'Pattern space' dans sed

@Ed Morton :Je ne suis pas d'accord avec vous ici. J'ai trouvé sed très utile et simple (une fois que vous avez compris le concept du motif et maintenez les tampons) pour trouver une manière élégante de faire du grappin multiligne.

Par exemple, prenons un fichier texte contenant des noms d'hôte et des informations sur chaque hôte, avec beaucoup de fichiers indésirables entre lesquels je ne me soucie pas.

Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter

Pour moi, un script awk pour obtenir simplement les lignes avec le nom d'hôte et le info correspondant prendrait un peu plus de temps que ce que je suis capable de faire avec sed :

sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt

la sortie ressemble à :

Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!

(Notez que Host: foo1 apparaît deux fois dans la sortie.)

Explication :

  1. -n désactive la sortie à moins qu'elle ne soit explicitement imprimée
  2. première correspondance, trouve et place le Host: ligne dans le tampon de maintien (h)
  3. deuxième correspondance, trouve la prochaine ligne Info :, mais échange d'abord (x) la ligne actuelle dans le tampon de modèle avec le tampon de maintien, et imprime (p) le Host: ligne, puis rééchange (x) et imprime (p) la ligne Info :.

Oui, c'est un exemple simpliste, mais je soupçonne qu'il s'agit d'un problème courant qui a été rapidement traité par un simple sed one-liner. Pour des tâches beaucoup plus complexes, telles que celles dans lesquelles vous ne pouvez pas compter sur une séquence donnée et prévisible, awk peut être mieux adapté.


Lorsque sed lit un fichier ligne par ligne, la ligne actuellement lue est insérée dans le motif tampon (espace de motif). Le tampon de modèle est comme le tampon temporaire, le bloc-notes où les informations actuelles sont stockées. Lorsque vous dites à sed d'imprimer, il imprime le tampon de modèle.

Hold buffer / hold space est comme un stockage à long terme, de sorte que vous pouvez attraper quelque chose, le stocker et le réutiliser plus tard lorsque sed traite une autre ligne. Vous ne traitez pas directement l'espace de maintien, mais vous devez le copier ou l'ajouter à l'espace de modèle si vous voulez en faire quelque chose. Par exemple, la commande d'impression p imprime uniquement l'espace du motif. De même, s opère sur l'espace du motif.

Voici un exemple :

sed -n '1!G;h;$p'

(l'option -n supprime l'impression automatique des lignes)

Il y a trois commandes ici :1!G , h et $p . 1!G a une adresse, 1 (première ligne), mais le ! signifie que la commande sera exécutée partout sauf sur la première ligne. $p par contre ne sera exécuté que sur la dernière ligne. Voici ce qui se passe :

  1. la première ligne est lue et insérée automatiquement dans l'espace du modèle
  2. sur la première ligne, la première commande n'est pas exécutée ; h copie la première ligne dans le hold espace.
  3. maintenant la deuxième ligne remplace tout ce qui était dans l'espace du motif
  4. sur la deuxième ligne, nous exécutons d'abord G , en ajoutant le contenu du tampon de maintien au tampon de modèle, en le séparant par une nouvelle ligne. L'espace de modèle contient maintenant la deuxième ligne, une nouvelle ligne et la première ligne.
  5. Ensuite, h La commande insère le contenu concaténé du tampon de modèle dans l'espace de maintien, qui contient maintenant les lignes inversées deux et un.
  6. Nous passons à la ligne 3 :passez au point (3) ci-dessus.

Enfin, après que la dernière ligne a été lue et que l'espace de maintien (contenant toutes les lignes précédentes dans l'ordre inverse) a été ajouté à l'espace du motif, l'espace du motif est imprimé avec p . Comme vous l'avez deviné, ce qui précède fait exactement ce que le tac la commande fait -- imprime le fichier à l'envers.


Bien que la réponse de @January et l'exemple soient sympas, l'explication ne me suffisait pas. J'ai dû chercher et apprendre beaucoup jusqu'à ce que je parvienne à comprendre exactement comment sed -n '1!G;h;$p' œuvres. J'aimerais donc élaborer sur la commande pour quelqu'un comme moi.

Tout d'abord, voyons ce que fait la commande.

$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a

Il inverse l'entrée comme tac la commande le fait.

sed lit ligne par ligne, alors voyons ce qui se passe sur l'espace de motif et l'espace de maintien à chaque ligne. Comme h copie le contenu de l'espace de motif dans l'espace de maintien, les deux espaces ont le même texte.

Read line    Pattern Space / Hold Space    Command executed
-----------------------------------------------------------
a            a$                            h
b            b\na$                         1!G;h
c            c\nb\na$                      1!G;h
d            d\nc\nb\na$                   1!G;h;$p

À la dernière ligne, $p imprime d\nc\nb\na$ qui est formaté pour

d
c
b
a

Si vous voulez voir l'espacement du motif pour chaque ligne, vous pouvez ajouter un l commande.

$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a

J'ai trouvé très utile de regarder ce didacticiel vidéo Comprendre le fonctionnement de sed, car le gars montre comment chaque espace sera utilisé étape par étape. Le maintien espacé est mentionné dans le 4ème tutoriel, mais je vous recommande de regarder toutes les vidéos si vous n'êtes pas familier avec sed .

Le document GNU sed et le tutoriel Sed de Bruce Barnett sont également de très bonnes références.


Linux
  1. Comment utiliser la commande Linux sed

  2. La commande Linux Sed :utilisation et exemples

  3. Manipuler les saisies de la touche X et du pointeur sur la ligne de commande ?

  4. Comment insérer du texte avant la première ligne d'un fichier ?

  5. Imprimer la ligne correspondante et la nième ligne à partir de la ligne correspondante ?

Apprendre à utiliser l'éditeur de texte Sed

Ohcount - Le compteur et l'analyseur de lignes de code source

Remplacer toutes les nouvelles lignes par un espace sauf la dernière ?

Comment la commande Sed '1!g;h;$!d' inverse-t-elle le contenu d'un fichier ?

Tutoriel Unix Sed :7 exemples d'opérations Sed Hold et Pattern Buffer

MySQL la ligne de commande et les pagers