En sed o awk, ¿cómo manejo separadores de registros que * pueden * abarcar varias líneas?

StackOverflow https://stackoverflow.com/questions/310191

  •  10-07-2019
  •  | 
  •  

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
¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top