¿Cómo imprimir solo una coincidencia de grep cuando tail -f?

Estoy leyendo un logging activo y tratando de get algunas llamadas especiales

$ tail -f example.log | egrep 'pattern1|pattern2|pattern3|pattern4|pattern5' 

Pero un par de patrones apenas se imprimen (debido al flujo dev) y el otro se imprime de forma muy continua.

¿Cómo puedo hacer que egrep imprima solo una request para cada patrón para que pueda ver fácilmente que están funcionando bien?

Podrías hacer algo como:

 tail -f example.log | awk ' BEGIN { n = split("pattern1,pattern2,pattern3,pattern4,pattern5", pats, /,/) } { found=0 for (i in pats) if ($0 ~ pats[i]) { found=1 delete pats[i] n-- } } found {print; if (!n) exit}' 

Tenga en count que awk saldrá tan pronto como haya visto todos los patrones, pero tail solo saldrá (de un SIGPIPE) solo la próxima vez que escriba algo después de eso.

O si las líneas pueden no coincidir con varios patrones y si no te importa salir cuando se encuentran todos los patrones, más cortos pero less eficientes:

 awk '/pattern1/&&!a++ || /pattern2/&&!b++ || /pattern3/&&!c++ || \ /pattern4/&&!d++ || /pattern5/&&!e++' 

Con zsh y GNU grep :

 (trap '' PIPE;tail -f example.log > >(grep -m1 pattern1) \ > >(grep -m1 pattern2) \ > >(grep -m1 pattern3) \ > >(grep -m1 pattern4) \ > >(grep -m1 pattern5)) 

Pero tenga en count que las líneas que coincidan con varios patrones se imprimirán tantas veces.

Creo que está buscando -o que imprimirá solo la parte coincidente. Entonces podrías hacer lo siguiente:

 cat example.log | egrep -o 'pat1|pat2|pat3|pat4|pat5' | sort | uniq 

Si el resultado contiene un patrón, es porque al less una línea coincide con ese patrón. Si la salida contiene los 5 patrones, cada patrón coincide al less con una línea.

No funciona con expresiones regulares que pueden coincidir con diferentes caracteres o coincidencias de diferente duración.

Otro enfoque podría ser dar salida a las líneas que coinciden con cada patrón sobre el anterior en su propia línea como con:

 #! /bin/sh tput rmam # no line wrap for terminals that can do it awk -vu="$(tput cuu1)" -v el="$(tput el)" ' BEGIN { for (n = 0; n < ARGC; n++) pat[n] = ARGV[n] ARGC=0 } { pre = ""; post = el "\r" u for (i = 1; i < n; i++) { if ($0 ~ pat[i]) print pre $0 post pre = pre "\n" post = post u } } END{printf "%s", pre}' "$@" tput smam 

Llamado:

 tail -f example.log | that-script pattern1 pattern2... 

Ejemplo:

enter image description here