En sed o awk, ¿cómo manejo separadores de registros que * pueden * abarcar varias líneas?
Pregunta
Mi archivo de registro es:
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah
Wed Nov 12 blah blah blah blah
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
Quiero analizar las entradas multilíneas completas donde se encuentra cat en la primera línea. ¿Cuál es la mejor manera de hacer esto en sed
y / o awk
?
es decir quiero que mi análisis produzca:
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
Solución
si dice que cada línea que comienza con un espacio es una continuación del seguimiento es fácil con (g) awk (esto es de mi memoria, por lo que tal vez contiene algunos errores tipográficos menores y para una mejor legibilidad con algunos saltos de línea adicionales):
awk " BEGIN { multiline = 0;}
! /^ / { if (whatever)
{ print; multiline = 1;}
else
multiline = 0;
}
/^ / {if (multiline == 1)
print;
}
"
yourfile
donde sea lo que sea
es su verificación si su salida debería ocurrir (por ejemplo, para el gato).
Otros consejos
Suponiendo que su archivo de registro no contiene los caracteres de control '\ 01'
y '\ 02'
, y que una línea continua comienza con exactamente cuatro espacios, el siguiente podría funcionar:
c1=`echo -en '\01'`
c2=`echo -en '\02'`
cat logfile | tr '\n' $c1 | sed "s/$c1 /$c2/g" | sed "s/$c1/\n/g" | grep cat | sed "s/$c2/\n /g"
Explicación: esto reemplaza cada nueva línea con ASCII 1 (un carácter de control que nunca debería aparecer en un archivo de registro) y cada secuencia " newline-space-space-space-space " con ASCII 2 (otro personaje de control). Luego, reemplaza ASCII 1 con nuevas líneas, por lo que ahora cada secuencia de varias líneas se coloca en una línea, con los saltos de línea anteriores reemplazados por ASCII 2. Esto se selecciona para cat, y luego los ASCII 2 se reemplazan con el combinación newline-space-space-space-space.
¿Algo como esto?
awk 'function print_part() { if(cat) print part } /^ / { part = part "\n" <*>; next } /cat[0-9]$/ { print_part(); part = <*>; cat = 1; next; } { print_part(); cat=0} END { print_part() }' inputfile
La expresión regular / ^ /
identifica las líneas de continuación.
La / cat [0-9] $ /
regexp identifica las líneas de inicio que desea conservar.
Otro enfoque sería establecer RS
para que sea algo diferente al \ n
normal. Por ejemplo:
$ awk -v Pre=Wed 'BEGIN {RS = "\\n?\\s*" Pre} /cat.\n?/ {print Pre <*>}' file.log
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4