I have a file like the following and I would like to print the lines between two given patterns PAT1
and PAT2
.
Using grep
with PCRE (where available) to print markers and lines between markers:
$ grep -Pzo "(?s)(PAT1(.*?)(PAT2|\Z))" file
PAT1
3 - first block
4
PAT2
PAT1
7 - second block
PAT2
PAT1
10 - third block
-P
perl-regexp, PCRE. Not in all grep
variants-z
Treat the input as a set of lines, each
terminated by a zero byte instead of a newline -o
print only matching(?s)
DotAll, ie. dot finds newlines as well (.*?)
nongreedy find\Z
Match only at end of string, or before newline at the endPrint lines between markers excluding end marker:
$ grep -Pzo "(?s)(PAT1(.*?)(?=(\nPAT2|\Z)))" file
PAT1
3 - first block
4
PAT1
7 - second block
PAT1
10 - third block
(.*?)(?=(\nPAT2|\Z))
nongreedy find with lookahead for \nPAT2
and \Z
Print lines between markers excluding markers:
$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(?=(\nPAT2|\Z)))" file
3 - first block
4
7 - second block
10 - third block
(?<=PAT1\n)
positive lookbehind for PAT1\n
Print lines between markers excluding start marker:
$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(PAT2|\Z))" file
3 - first block
4
PAT2
7 - second block
PAT2
10 - third block