Bash, grep tra due righe con una stringa specificata

Esempio:

a43 test1 abc cvb bnm test2 kfo 

Ho bisogno di tutte le linee tra test1 e test2. Il grep normale non funziona in questo caso. Hai qualche proposta?

Lei è un po ‘ awk Questi stamperanno da test2 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 

Questi stampa i dati tra test2 a test2

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

 abc cvb bnm 

Potresti usare sed :

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

Per escludere le righe contenenti test2 e test2 , dì:

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

Se puoi usare solo grep:

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

grep -A e poi un numero ottiene le linee dopo la stringa corrispondente, e grep -B ottiene le linee prima della stringa corrispondente. Il numero, 100000 in questo caso, deve essere abbastanza grande da includere tutte le linee prima e dopo.

Se non vuoi includere test1 e test2, puoi rimuoverli in seguito con grep -v , che stampa tutto tranne le linee corrispondenti:

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

o tutto in una riga:

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

Sì, la grep normale non lo farà. Ma grep con parametro -P farà questo lavoro.

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

\K scarta i caratteri precedentemente abbinati dalla stampa finale e il lookahead positivo (?=\ntest2) asserisce che la corrispondenza deve essere seguita da un carattere \n carattere di nuova riga e quindi test2 stringa test2 .

La risposta di PratPor sopra:

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

è bello .. ma se non conosci la lunghezza del file:

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

Non deterministico, ma non troppo male. Qualcuno ha di meglio (più deterministico)?

Lo script seguente avvolge questo processo. Maggiori dettagli in questo post StackOverflow simile

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 $* 

Puoi fare qualcosa di simile anche a questo. Ti dico questo file test.txt con contenuto:

 a43 test1 abc cvb bnm test2 kfo 

Tu puoi fare

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

dove -A è quello di ottenere n righe dopo la corrispondenza nel file e -B è di darti n righe prima della partita. Devi solo assicurarti che n > number of expected lines between test1 and test2 . Oppure puoi dargli abbastanza spazio per raggiungere EOF.

Risultato:

 test1 abc cvb bnm test2