Bash, grep entre dos líneas con una cadena especificada

Ejemplo:

a43 test1 abc cvb bnm test2 kfo 

Necesito todas las líneas entre test1 y test2. Grep normal no funciona en este caso. ¿Tienes alguna proposición?

Ella es un poco awk Estas se imprimirán de test1 a test2

 awk '/test1/{f=1} /test2/{f=0;print} f' awk '/test1/{f=1} f; /test2/{f=0}' awk '/test1/,/test2/' 

 test1 abc cvb bnm test2 

Estos imprimen datos entre test1 a test2

 awk '/test1/{f=1;next} /test2/{f=0} f' awk '/test2/{f=0} f; /test1/{f=1}' 

 abc cvb bnm 

Puedes usar sed :

 sed -n '/test1/,/test2/p' filename 

Para excluir las líneas que contienen test1 y test2 , diga:

 sed -n '/test1/,/test2/{/test1/b;/test2/b;p}' filename 

Si solo puedes usar grep:

 grep -A100000 test1 file.txt | grep -B100000 test2 > new.txt 

grep -A y luego un número obtiene las líneas después de la cadena correspondiente, y grep -B obtiene las líneas antes de la cadena correspondiente. El número, 100000 en este caso, debe ser lo suficientemente grande como para incluir todas las líneas antes y después.

Si no desea incluir test1 y test2, puede eliminarlos luego mediante grep -v , que imprime todo excepto la (s) línea (s) correspondiente (s):

 egrep -v "test1|test2" new.txt > newer.txt 

o todo en una línea:

 grep -A100000 test1 file.txt | grep -B100000 test2 | egrep -v "test1|test2" > new.txt 

Sí, grep normal no hará esto. Pero grep con el parámetro -P hará este trabajo.

 $ grep -ozP '(?s)test1\n\K.*?(?=\ntest2)' file abc cvb bnm 

\K descarta que los caracteres previamente coincidentes se (?=\ntest2) en la final y el aspecto positivo hacia (?=\ntest2) afirma que la coincidencia debe ir seguida de un \n carácter de nueva línea y luego una cadena de test2 .

La respuesta de PratPor arriba:

 cat test.txt | grep -A10 test1 | grep -B10 test2 

es genial … pero si no sabes la longitud del archivo:

 cat test.txt | grep -A1000 test1 | grep -B1000 test2 

No es determinista, pero no está mal. ¿Alguien tiene mejor (más determinista)?

La siguiente secuencia de comandos finaliza este proceso. Más detalles en esta publicación similar de StackOverflow

get_text.sh

 function show_help() { HELP=$(doMain $0 HELP) echo "$HELP" exit; } function doMain() { if [ "$1" == "help" ] then show_help fi if [ -z "$1" ] then show_help fi if [ -z "$2" ] then show_help fi FILENAME=$1 if [ ! -f $FILENAME ]; then echo "File not found: $FILENAME" exit; fi if [ -z "$3" ] then START_TAG=$2_START END_TAG=$2_END else START_TAG=$2 END_TAG=$3 fi CMD="cat $FILENAME | awk '/$START_TAG/{f=1;next} /$END_TAG/{f=0} f'" eval $CMD } function help_txt() { HELP_START get_text.sh: extracts lines in a file between two tags usage: FILENAME {TAG_PREFIX|START_TAG} {END_TAG} examples: get_text.sh 1.txt AA => extracts lines in file 1.txt between AA_START and AA_END get_text.sh 1.txt AA BB => extracts lines in file 1.txt between AA and BB HELP_END } doMain $* 

Usted puede hacer algo como esto también. Permite decir que este archivo test.txt con contenido:

 a43 test1 abc cvb bnm test2 kfo 

Tu puedes hacer

cat test.txt | grep -A10 test1 | grep -B10 test2

donde -A es para obtener n líneas después de su coincidencia en el archivo y -B es para darle n líneas antes de la coincidencia. Solo tiene que asegurarse de que n > number of expected lines between test1 and test2 . O puede darlelo lo suficientemente grande como para llegar a EOF.

Resultado:

 test1 abc cvb bnm test2