как извлечь часть текста из файла между совпавшими условиями

как извлечь часть текста из файла между совпавшими условиями

У меня есть файл, как показано ниже.

~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

Если я пройду PAR1, я должен получить все строки между PAR1и Par Finishedстрокой. Как мне это получить? Я искал awkи sedи не смог найти никаких вариантов.

решение1

Если вам нужна строка верхнего и нижнего колонтитула, то это довольно просто сделать, sed например, так:

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

Это просто использовать с переменной

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

Мы также можем сделать последнюю строку переменной.

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

Результат выглядит так:

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

Par Finished

Теперь, если вам не нужны начальная/конечная строки и не нужна пустая строка, то все немного сложнее.

Возможно, есть способы и получше, но мне подходит этот:

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

Результатом этого является

This is Par1 line 1
This is Par1 line 2

решение2

Вы можете использовать Par Finishedстроку (с необязательными конечными пустыми строками) в качестве разделителя записей (а затем заменить ее, чтобы завершить запись)

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

Если у вас есть GNUawk, вы можете восстановить разделитель записей с помощью специальной переменной RT(удалив лишние символы новой строки, если хотите)

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

Конечно, если вам не нужно проходитьпеременная Par1вы используете простой диапазон регулярных выражений

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

Par Finished

решение3

С grepи pcreдля достаточно маленького входного файла

$ 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

Чтобы получить линии между шаблонами:

$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Пара завершена)" ip.txt
Это Par1 строка 1
Это Par1 строка 2

Изменение переменной наPAR2

$ s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Пара завершена)" ip.txt
Это Par2 строка 1
Это Par2 строка 2

Ссылка: Регулярное выражение (grep) для многострочного поиска

Связанный контент