
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
f
es verdadera (distinta de cero), agregue la línea actual al final de la variablea
./Condition 1/{a=$0; f=1}
Si la línea actual contiene
Condition 1
, configúrelos
en la línea actual y establezca la variablef
en 1.f && /Condition 2/{print a; f=0}
Si
f
es verdadero y la línea actual contieneCondition 2
, imprima la variablea
yf
vuelva 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 vi
su predecesor inmediato): muy flexible.
printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out
Esto significa:
Para cada línea ( g
lobalmente) que coincida con el patrón "Condición 2", busque hacia atrás la instancia inmediatamente anterior de "Condición 1" e p
imprima 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_2
está precedida por al menos una línea coincidente PATTERN_1
. Para el caso más general, agregue otra condición para probar la PATTERN_1
presencia 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
-0777
y-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
).