
Estoy siguiendo un archivo de registro con el indicador -f. Luego estoy canalizando esto a grep, para encontrar solo líneas que contengan "X". Eso está funcionando perfectamente bien. Ahora quiero canalizar esto nuevamente a otro grep, que eliminará todas las líneas que contienen "Y". Cuando agrego la segunda tubería, el archivo deja de actualizarse y parece que no llegan datos.
Este es el comando que funciona: tail -f my_file.log | grep "X"
Este es el comando que no: tail -f my_file.log | grep "X" | grep -v "Y"
¿Cómo debo estructurar esto para que el comando funcione?
Respuesta1
Como la salida de grep
está almacenada en el búfer, use --line-buffered
la opción de grep
para habilitar el almacenamiento en búfer de línea:
tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'
Si grep
no tienes la opción, puedes utilizar stdbuf
como alternativa:
tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
Respuesta2
Normalmente encuentro más útil awk
para este tipo de comprobaciones lógicas:
tail -f /path/to/log | awk '/X/ && !/Y/'
# ^^^ ^^^^
# this I want but not this
Probado al tener dos pestañas, una en la que sigo escribiendo seq 20 >> myfile
y la otra que tiene por ejemplo tail -f myfile | awk '/3/ && !/13/'
.
Respuesta3
Otro enfoque sería utilizar una única grep
invocación en lugar de dos y así evitar el problema del almacenamiento en búfer. Simplemente use expresiones regulares que coincidan con líneas que constan de 0 o más caracteres que no sean Y, luego una X y luego 0 o más caracteres que no sean Y nuevamente hasta el final de la línea.
tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'