114 votes

Le concept de "Hold space" et de "Pattern space" dans le sed

Je suis confus par les deux concepts de sed : l'espace de maintien et l'espace de motif. Quelqu'un peut-il m'aider à les expliquer ?

Voici un extrait du manuel :

h H    Copy/append pattern space to hold space.
g G    Copy/append hold space to pattern space.

n N    Read/append the next line of input into the pattern space.

Ces six commandes me déroutent vraiment.

146voto

January Points 3990

Lorsque sed lit un fichier ligne par ligne, la ligne qui vient d'être lue est insérée dans la section motif tampon (espace de motif). Le tampon de motifs est comme le tampon temporaire, le bloc-notes où sont stockées les informations courantes. Lorsque vous demandez à sed d'imprimer, il imprime le tampon de motifs.

Le tampon de maintien / l'espace de maintien 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 d'attente, au lieu de cela, vous devez le copier ou l'ajouter à l'espace de motif si vous voulez en faire quelque chose. Par exemple, la commande print p imprime uniquement l'espace du motif. De même, s opère sur l'espace des motifs.

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 y $p . 1!G a une adresse, 1 (première ligne), mais le ! signifie que la commande sera exécutée partout mais sur la première ligne. $p par contre, ne sera exécuté que sur la dernière ligne. Voici donc ce qui se passe :

  1. la première ligne est lue et insérée automatiquement dans l'espace du motif
  2. sur la première ligne, la première commande n'est pas exécutée ; h copie la première ligne dans le fichier tenir espace.
  3. maintenant la deuxième ligne remplace 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 motif, en le séparant par une nouvelle ligne. L'espace de motif contient maintenant la deuxième ligne, une nouvelle ligne, et la première ligne.
  5. Ensuite, h insère le contenu concaténé du tampon de motifs dans l'espace de maintien, qui contient maintenant les lignes inversées deux et un.
  6. Nous passons à la ligne numéro trois -- allez au point (3) ci-dessus.

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

27voto

Jens Jensen Points 11

Ed Morton : Je ne suis pas d'accord avec vous. J'ai trouvé sed très utile et simple (une fois que l'on a compris le concept des tampons pattern et hold) pour trouver une façon élégante de faire du grepping multi-lignes.

Par exemple, prenons un fichier texte contenant des noms d'hôtes et des informations sur chaque hôte, ainsi qu'un tas d'autres informations dont 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 awk script pour obtenir juste les lignes avec le nom d'hôte et le correspondant info Il faudrait un peu plus que ce que je suis capable de faire avec sed :

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

La sortie ressemble à ça :

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 sauf si elle est explicitement imprimée
  2. première correspondance, trouve et place le Host: ligne dans le tampon d'attente (h)
  3. deuxième correspondance, trouve la ligne Info : suivante, mais échange d'abord (x) la ligne courante du tampon de motifs avec le tampon de maintien, et imprime (p) la ligne Info : suivante. Host: puis ré-échanger (x) et imprimer (p) la ligne Info :.

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

25voto

Sangdol Points 3374

Bien que la réponse de @January et l'exemple soient sympathiques, l'explication n'était pas suffisante pour moi. J'ai dû chercher et apprendre beaucoup de choses jusqu'à ce que je parvienne à comprendre comment exactement sed -n '1!G;h;$p' fonctionne. J'aimerais donc donner des précisions 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 fait.

sed lit ligne par ligne, alors voyons ce qui se passe sur la page espace de patte et le tenir l'espace à chaque ligne. Comme h copie le contenu de l'espace motif dans l'espace 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

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

d
c
b
a

Si vous voulez voir l'espace du motif pour chaque ligne, vous pouvez ajouter une fonction l commandement.

$ 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 tutoriel vidéo. Comprendre le fonctionnement de sed car le type montre comment chaque espace sera utilisé, étape par étape. Le maintien espacé est référencé dans le 4ème tutoriel, mais je recommande de regarder toutes les vidéos si vous n'êtes pas familiarisé avec sed .

Aussi Document sur GNU sed y Le tutoriel Sed de Bruce Barnett sont de très bonnes références.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X