Redirección de salida dependiendo de grep regex


8

Estoy usando gradle runpara iniciar un servidor REST. La salida del servidor REST se ve así:

XXX.XXX.XX.XXX - <moreinfo>
randomtext
randomtext
XXX.XXX.XX.XXX - <moreinfo>
XXX.XXX.XX.XXX - <moreinfo>
randomtext
XXX.XXX.XX.XXX - <moreinfo>

XXX.XXX.XX.XXXAquí hay una dirección IP, el texto aleatorio son mensajes de error. Toda la salida se dirige a stdout, lamentablemente.

¿Cómo puedo dirigir todas las líneas que comienzan con una dirección IP a un archivo llamado err.logy todas las demás líneas all.log?

Desafortunadamente, gradle runsolo se puede iniciar una vez y no se detiene, ya que es un servidor REST.

Tal vez utilizar una tee, grepcombinación?

Respuestas:


8

En Bash, puede usar la sustitución de procesos con tee:

tee >(grep XXX > err.log) | grep -v XXX > all.log

Esto colocará todas las líneas que coincidan con XXX err.logy todas las líneas all.log. >( ... )crea el proceso entre paréntesis y conecta su salida estándar a una tubería. Esto funciona en zsh y otras conchas modernas también.

También puede usar el peecomando de moreutils :

pee "grep XXX > err.log" "grep -v XXX > all.log"

pee redirige la entrada estándar a múltiples comandos ("tee para tuberías").

Otra alternativa es con awk:

awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'

Eso solo prueba cada línea contra la expresión y escribe todo en err.logsi coincide o all.logno.

La expresión regular awk también es adecuada grep -E(aunque coincide con algunas direcciones incorrectas, 999.0.0.0etc., pero eso probablemente no sea un problema).


Hmm err.logestá vacío y toda la salida se redirige al all.loguso del teecomando anterior.
polym

Verifique que su expresión regular realmente coincida con las líneas correctas; si err.logexiste, el comando se ejecutó pero no salió nada. grep -Econ la expresión utilizada en el comando awk debería coincidir, o lo hace aquí.
Michael Homer

Ah ok lo tengo ¿Puedes modificar tu pregunta para que all.logno contenga las líneas coincidentes en la expresión grep?
polym

Hecho, no estaba seguro de cuál querías, así que tuve ambas.
Michael Homer

Oh, lo siento, funcionó. Sobreescribí all.logy err.logcon un viejo comando. Perdón por la confusion. Gracias, eres increíble :)) !!
polym

4

Por lo tanto, parece que gradle runno cumpla con tee, pee, grepy io-redirección. Siempre deja de leer después de 4096 bytes.

Para evitar este problema, readcada línea de gradle run. Todavía no lo probé, pero supongo que la lectura de una línea de más de 4k caracteres también fallará.

De todos modos, aquí está el código para resolver mi pregunta específicamente:

#!/bin/bash
STDOUTLOG="/log/stdout.txt"
STDERRLOG="/log/stderr.txt"
while read -r line; do
    [[ $line =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.* ]] && printf '%s\n' "$line" >> "$STDERRLOG" && continue
    printf '%s\n' "$line" >> "$STDOUTLOG"
done < <(gradle run)

1
Debe utilizar read -r liney printf '%s\n' "$line"para evitar algunos bordes casos rompiendo cosas.
nyuszika7h

@ nyuszika7h ¡Gracias! Modifiqué la respuesta en consecuencia :).
polym
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.