cómo extraer una porción de texto de un archivo entre condiciones coincidentes

cómo extraer una porción de texto de un archivo entre condiciones coincidentes

Tengo un archivo como el siguiente.

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

~PAR2~
This is Par2 line 1
This is Par2 line 2

Par Finished

Si paso PAR1, debería obtener todas las líneas entre PAR1y Par Finishedla línea. ¿Cómo puedo obtenerlo? Estuve investigando awky sedno encontré ninguna opción.

Respuesta1

Si desea la línea de encabezado y pie de página, entonces es bastante simple con sed , por ejemplo,

sed -n "/^~PAR1~$/,/Par Finished/p"

Esto es fácil de usar con una variable.

START=PAR1
sed -n "/^~$START~$/,/Par Finished/p"

También podemos hacer que la última línea sea una variable.

START=PAR1
END="Par Finished"
sed -n "/^~$START~$/,/$END/p"

El resultado se parece a:

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Ahora bien, si no desea las líneas de inicio/final y no desea la línea en blanco, entonces es un poco más complicado.

Puede que haya mejores formas, pero esta funciona para mí:

sed -n "/^~$START~$/,/$END/ { /^~$START~$/d ; /$END/d ; /^$/d ; p }"

El resultado de esto es

This is Par1 line 1
This is Par1 line 2

Respuesta2

Puede usar la Par Finishedlínea (con líneas en blanco al final opcionales) como separador de registros (y luego reemplazarla para completar el registro)

awk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {print $0,"\nPar Finished"}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Si tiene GNUawk, puede recuperar el separador de registros con la variable especial RT(eliminando las nuevas líneas adicionales si lo desea)

gawk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {sub("\n*$", "", RT); print $0,RT}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Por supuesto, si no necesitas aprobar unvariable Par1usas un rango de expresiones regulares simple

awk '/PAR1/,/Par Finished/' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Respuesta3

Con grepy pcrepara entrada de archivos suficientemente pequeños

$ s="PAR1"

$ grep -oPz "(?s)[^\n]*${s}.*?\n.*?Par Finished.*?\n" ip.txt 
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Para obtener líneas entre el patrón:

$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par Terminado)" ip.txt
Este es el Par1 línea 1
Este es el Par1 línea 2

Cambiando variable aPAR2

$s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par finalizado)" ip.txt
Este es el Par2 línea 1
Este es el Par2 línea 2

Referencia: Regex (grep) para búsqueda de varias líneas

información relacionada