segue um arquivo de log, mas mostra apenas linhas específicas

23

Estou seguindo um arquivo de log com o sinalizador -f. Então eu estou piping isso para grep, para encontrar apenas as linhas que contêm "X". Isso está funcionando perfeitamente bem. Agora eu quero canalizar isso novamente em outro grep, que irá remover todas as linhas contendo "Y". Quando eu adiciono o segundo pipe, o arquivo para de atualizar e parece que nenhum dado está chegando.

Este é o comando que funciona: tail -f my_file.log | grep "X"

Este é o comando que não: tail -f my_file.log | grep "X" | grep -v "Y"

Como devo estruturar isso para que o comando funcione?

    
por Ori Horev 13.10.2015 / 15:10

3 respostas

29

Como a saída de grep é armazenada em buffer, use a opção --line-buffered de grep para ativar o buffer de linha:

tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'

Se o seu grep não tiver a opção, você poderá usar stdbuf como alternativa:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
    
por heemayl 13.10.2015 / 15:28
17

Normalmente, acho mais útil awk para esse tipo de verificação lógica:

tail -f /path/to/log | awk '/X/ && !/Y/'
#                           ^^^    ^^^^
#                   this I want    but not this

Testado por ter duas guias, uma na qual eu continuo escrevendo seq 20 >> myfile e a outra tendo por exemplo tail -f myfile | awk '/3/ && !/13/' .

    
por fedorqui 13.10.2015 / 16:42
15

Outra abordagem seria usar uma única invocação grep em vez de duas e assim evitar o problema de buffer. Basta usar expressões regulares que correspondam a linhas que consistam em 0 ou mais caracteres não Y, depois um X e, em seguida, 0 ou mais não Ys até o final da linha "

tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'
    
por terdon 13.10.2015 / 16:36