
Estou seguindo um arquivo de log com o sinalizador -f. Então estou canalizando isso para o grep, para encontrar apenas linhas que contenham "X". Isso está funcionando perfeitamente bem. Agora quero canalizar isso novamente para outro grep, que removerá todas as linhas que contêm "Y". Quando adiciono o segundo pipe, o arquivo para de ser atualizado 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?
Responder1
Como a saída de grep
é armazenada em buffer, use --line-buffered
a opção de grep
para ativar o buffer de linha:
tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'
Caso grep
não tenha essa opção, você pode usar stdbuf
como alternativa:
tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
Responder2
Normalmente acho mais útil awk
esse tipo de verificação lógica:
tail -f /path/to/log | awk '/X/ && !/Y/'
# ^^^ ^^^^
# this I want but not this
Testado tendo duas abas, uma na qual continuo escrevendo seq 20 >> myfile
e outra tendo por exemplo tail -f myfile | awk '/3/ && !/13/'
.
Responder3
Outra abordagem seria usar uma única grep
invocação em vez de duas e assim evitar o problema de buffer. Basta usar expressões regulares que correspondam a linhas que consistem em 0 ou mais caracteres diferentes de Y, depois um X e, em seguida, 0 ou mais caracteres diferentes de Y novamente até o final da linha"
tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'