La impresión abarca desde la última aparición de un determinado patrón hasta la primera aparición de otro patrón.

La impresión abarca desde la última aparición de un determinado patrón hasta la primera aparición de otro patrón.

Buenos días, esto es muy similar a la pregunta.Grep desde la última aparición de un patrón a otro patrón(varios meses), mientras agrega un poco más de detalle.

Estoy intentando escribir un script UNIX para un archivo con múltiples patrones duplicados, seguido del patrón que estoy buscando. Sin embargo, no tengo 'tac' o 'tail -r' (usando el emulador UNIX, MKS Toolkit) y estoy buscando devolver la última aparición de Pattern1 antes de Pattern2, seguida de los datos entre Pattern1 y Pattern2, y luego Pattern2. también. Los Patrones en este caso serían 'Condición 1' y 'Condición 2':

salida.salida:

...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...

Me gustaría escribir un script awk (o sed, pero pensé que awk sería la herramienta adecuada) para devolver:

Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Supongo que es alguna forma de la línea siguiente, pero no puedo entender la sintaxis correcta:

awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out

Trabajar con '/,/' es donde parece que tengo problemas. Me preguntaba si alguien tenía algún consejo, sería muy apreciado. Muchas gracias por cualquier ayuda y tiempo relacionado con esta pregunta.

Respuesta1

Intentar:

$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out 
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Cómo funciona

  • f{a=a"\n"$0}

    Si la variable fes verdadera (distinta de cero), agregue la línea actual al final de la variable a.

  • /Condition 1/{a=$0; f=1}

    Si la línea actual contiene Condition 1, configúrelo sen la línea actual y establezca la variable fen 1.

  • f && /Condition 2/{print a; f=0}

    Si fes verdadero y la línea actual contiene Condition 2, imprima la variable ay fvuelva a ponerla a cero.

Respuesta2

Cuando desee direccionamiento inverso en el procesamiento de texto, utiliceex

EsPOSIX especificado, y es la forma programable de vi(y visu predecesor inmediato): muy flexible.

printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out

Esto significa:

Para cada línea ( globalmente) que coincida con el patrón "Condición 2", busque hacia atrás la instancia inmediatamente anterior de "Condición 1" e pimprima todas las líneas desde esa línea hasta la línea actual ( .) (que es la línea con "Condición 2" en él).

La salida de la entrada proporcionada es exactamente como usted describe.

Respuesta3

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile

aunque esto supone que cualquier línea que coincida PATTERN_2está precedida por al menos una línea coincidente PATTERN_1. Para el caso más general, agregue otra condición para probar la PATTERN_1presencia en el espacio del patrón antes de imprimir:

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile

Respuesta4

Aquí hay un poco de perl malvado:

perl -0777 -ne '
    my $c1 = qr/Condition 1/;
    my $c2 = qr/Condition 2/;
    print for map {s/$c2.*?\n\K.*//s; $_}
              grep {/$c2/}
              split /(?=$c1)/ms;
' output.out

Él:

  • lee el archivo completo (usando las opciones -0777y -n),
  • lo divide donde aparece la Condición 1 ( split),
  • filtra los párrafos donde la Condición 2 no aparece ( grep),
  • luego elimina de cada párrafo interesante cualquier línea que siga a la línea de la Condición 2 ( map).

información relacionada