web-dev-qa-db-fra.com

La tuyauterie de grep vers awk ne fonctionne pas

J'essaie de grep le tail en cours du fichier journal et d'obtenir le nème mot à partir d'une ligne. Exemple de fichier:

$ cat > test.txt <<EOL
Beam goes blah
John goes hey
Beam goes what?
John goes forget it
Beam goes okay
Beam goes bye
EOL
^C

Maintenant, si je fais un tail:

$ tail -f test.txt
Beam goes blah
John goes hey
Beam goes what?
John goes forget it
Beam goes okay
Beam goes bye
^C

Si je grep que tail:

$ tail -f test.txt | grep Beam
Beam goes blah
Beam goes what?
Beam goes okay
Beam goes bye
^C

Mais si je awk que grep:

$ tail -f test.txt | grep Beam | awk '{print $3}'

Rien, peu importe combien de temps j'attends. Je soupçonne que cela a quelque chose à voir avec le fonctionnement du flux.

Quelqu'un a une idée?

35
Belmin Fernandez

C'est probablement la mise en mémoire tampon de sortie de grep. vous pouvez désactiver cela avec grep --line-buffered.

Mais vous n'avez pas besoin de diriger la sortie de grep vers awk. awk peut faire un motif regexp correspondant tout seul.

tail -f test.txt | awk '/Beam/ {print $3}'

57
cas

En utilisant tail -f test.txt | awk '/Beam/{print $3}' travaille pour moi. En plus d'utiliser tail -f test.txt | grep --line-buffered Beam | awk '{print $3}' (gnu grep).

Le problème ici est de savoir si awk a reçu les données ligne par ligne ou comme un bloc de données plus grand. La version GNU de grep envoie la sortie dans des blocs plus grands car elle est plus efficace, mais awk doit lire ligne par ligne afin de sortir ligne par ligne.

En d'autres termes: grep n'enverra des données que lorsque le tampon est rempli, awk attend que ce tampon soit rempli, donc il n'envoie rien.

8
Arcege

Voir le --line-buffered option de grep.

4
choroba