У меня есть файл, как показано ниже.
~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
Если у вас есть GNU
awk, вы можете восстановить разделитель записей с помощью специальной переменной 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) для многострочного поиска