Formatando a saída do grep com o awk. Caso simples e caso de fundo

2

Estou lutando com esse problema. Eu tenho essa linha:

mplayer *.* 2>/dev/null | grep Playing

que lança apenas mplayer e apenas a linha correspondente Playing filename é impressa na tela. Isso funciona também toda vez que eu mudo a mídia atualmente reproduzida.

Eu queria saber se era possível "formatar" a saída do grep. Por exemplo, se a saída for:

Playing Pink_Floyd-Wish_You_Were_Here.mp3  # I get this at the beginning
Playing Pearl_Jam-Once.mp3                 # I get this after I change media inside mplayer

então eu teria algo como:

Mplayer: Playing Pink_Floyd-Wish_You_Were_Here.mp3
Mplayer: Playing Pearl_Jam-Once.mp3

Para fazer isso, decidi empregar o awk:

mplayer *.* 2>/dev/null | grep Playing | awk '{print "Mplayer: "$1}'

Mas neste caso nada acontece; Eu não recebo saída !!!

Minha pergunta não é orientada para resolver o problema com o mplayer, mas para ter uma compreensão mais profunda sobre pipes no bash.

Por exemplo, se eu usar o seguinte:

echo a_song.mp3 | awk '{print "Mplayer: "$1}'

Eu obtenho o que eu quero

Mplayer: a_song.mp3

Por que o primeiro comando não funciona?

O que devo fazer se quiser executar mais de um processo como esse em segundo plano?

    
por the_candyman 25.04.2015 / 19:57

1 resposta

4

Muitas implementações do grep usam a linha em buffer quando a saída padrão é terminal. Quando a saída padrão é terminal, geralmente é uma sessão interativa, você deseja obter dados o mais rápido possível. Portanto, grep gravará os dados na saída padrão assim que visualizar uma nova linha.

Quando a saída padrão não é terminal (geralmente significa sessão não interativa), grep usará o buffer de bloco. Isso significa que grep não grava na saída padrão imediatamente ao ver uma nova linha. grep coleta a quantidade de dados (4096 bytes no Linux) antes de gravar na saída padrão.

Algum grep versão, como GNU grep ou BSD grep tem --buffered por linha . Isso faz com que grep sempre grave na saída padrão ao ver uma nova linha. Então, seu exemplo se tornará:

mplayer *.* 2>/dev/null | grep --line-buffered Playing | awk '{print "Mplayer: "$1}'

Se a sua versão grep não tiver --line-buffer , você pode fazer tudo com awk :

mplayer *.* 2>/dev/null | awk '/Playing/{print "Mplayer: "$1}'

O GNU coreutils tem uma ferramenta stdbuf para modificar o buffer de comando. Você sempre pode forçar o buffer de linha na saída padrão com:

stdbuf -oL command

Há também o comando unbuffer que desativa somente o buffer de saída.

Outras leituras

por 25.04.2015 / 20:32

Tags