How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)?
Print lines between PAT1 and PAT2
$ awk '/PAT1/,/PAT2/' file
PAT1
3 - first block
4
PAT2
PAT1
7 - second block
PAT2
PAT1
10 - third block
Or, using variables:
awk '/PAT1/{flag=1} flag; /PAT2/{flag=0}' file
How does this work?
/PAT1/
matches lines having this text, as well as/PAT2/
does./PAT1/{flag=1}
sets theflag
when the textPAT1
is found in a line./PAT2/{flag=0}
unsets theflag
when the textPAT2
is found in a line.flag
is a pattern with the default action, which is toprint $0
: ifflag
is equal 1 the line is printed. This way, it will print all those lines occurring from the timePAT1
occurs and up to the nextPAT2
is seen. This will also print the lines from the last match ofPAT1
up to the end of the file.
Print lines between PAT1 and PAT2 - not including PAT1 and PAT2
$ awk '/PAT1/{flag=1; next} /PAT2/{flag=0} flag' file
3 - first block
4
7 - second block
10 - third block
This uses next
to skip the line that contains PAT1
in order to avoid this being printed.
This call to next
can be dropped by reshuffling the blocks: awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file
.
Print lines between PAT1 and PAT2 - including PAT1
$ awk '/PAT1/{flag=1} /PAT2/{flag=0} flag' file
PAT1
3 - first block
4
PAT1
7 - second block
PAT1
10 - third block
By placing flag
at the very end, it triggers the action that was set on either PAT1 or PAT2: to print on PAT1, not to print on PAT2.
Print lines between PAT1 and PAT2 - including PAT2
$ awk 'flag; /PAT1/{flag=1} /PAT2/{flag=0}' file
3 - first block
4
PAT2
7 - second block
PAT2
10 - third block
By placing flag
at the very beginning, it triggers the action that was set previously and hence print the closing pattern but not the starting one.
Print lines between PAT1 and PAT2 - excluding lines from the last PAT1 to the end of file if no other PAT2 occurs
This is based on a solution by Ed Morton.
awk 'flag{
if (/PAT2/)
{printf "%s", buf; flag=0; buf=""}
else
buf = buf $0 ORS
}
/PAT1/ {flag=1}' file
As a one-liner:
$ awk 'flag{ if (/PAT2/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /PAT1/{flag=1}' file
3 - first block
4
7 - second block
# note the lack of third block, since no other PAT2 happens after it
This keeps all the selected lines in a buffer that gets populated from the moment PAT1 is found. Then, it keeps being filled with the following lines until PAT2 is found. In that point, it prints the stored content and empties the buffer.
Print all lines between two patterns, exclusive, first instance only (in sed, AWK or Perl)
With awk
(assumes that PATTERN1
and PATTERN2
are always present in pairs and either of them do not occur inside a pair)
$ cat ip.txt
aaa
PATTERN1
bbb
ccc
ddd
PATTERN2
eee
fff
PATTERN1
ggg
hhh
iii
PATTERN2
jjj
$ awk '/PATTERN2/{exit} f; /PATTERN1/{f=1}' ip.txt
bbb
ccc
ddd
/PATTERN1/{f=1}
set flag if/PATTERN1/
is matched/PATTERN2/{exit}
exit if/PATTERN2/
is matchedf;
print input line if flag is set
Generic solution, where the block required can be specified
$ awk -v b=1 '/PATTERN2/ && c==b{exit} c==b; /PATTERN1/{c++}' ip.txt
bbb
ccc
ddd
$ awk -v b=2 '/PATTERN2/ && c==b{exit} c==b; /PATTERN1/{c++}' ip.txt
2
46
how to print Lines Between Two Patterns in file using SED or AWK?
You may use this sed
:
sed -n '/MULTIPLE-RESOURCES/,/^###$/ { /###$/!p; }' file
### MULTIPLE-RESOURCES
#### Viewing Resource Information
> kubectl get svc, po
> kubectl get deploy, no
> kubectl get all
> kubectl get all --all-namespaces
## KUBECTL
How can I use sed to match between two patterns and get the next line after the second pattern?
You can use N
(syntax here is based on GNU sed
)
$ sed -n '/PATTERN1/,/PATTERN2/{/PATTERN2/N; p}' ip.txt
PATTERN1
B
PATTERN2
C
Using awk
$ awk '/PATTERN1/{f=1} f || (c && c--); /PATTERN2/{f=0; c=1}' ip.txt
PATTERN1
B
PATTERN2
C
which you can generalize using:
awk -v n=2 '/PATTERN1/{f=1} f || (c && c--); /PATTERN2/{f=0; c=n}'
Further Reading:
- How to print lines between two patterns, inclusive or exclusive
- Printing with sed or awk a line following a matching pattern
Output text between two patterns on the same line using sed command
For your current input you may use this sed
:
sed 's/.*begin \(.*\) end.*/\1/' file
not sure what is wrong
Difference is use of .*
after end
that matches text after last end
and discards in substitution.
However for your 2nd part if there are two end
words, sed
command won't work correctly as it will find last end
due to greedy matching of .*
.
e.g if your input is:
this is begin not sure what is wrong end and why not end
Then following awk
would work better:
awk -F 'begin | end' '{print $2}' file
not sure what is wrong
Quit after printing between two patterns using sed
What you need is:
sed -n '/pattern1/,/pattern2/{/pattern2/{q};p}' file
Which has the form:
sed -n '/PAT1/,/PAT2/{/PAT2/{q};p}'
Which breaks down as
sed -n '/PAT1/,/PAT2/
- locate the range betweenPAT1
andPAT2
and suppress printing;/PAT2/{q};
- if it matchesPAT2
quit (done);p
- print all lines that fell within/PAT1/,/PAT2/
before quit was reached.
Example Use/Output
With your input in file
, you would get:
$ sed -n '/pattern1/,/pattern2/{/pattern2/{q};p}' file
pattern1
example1
SED or AWK command that print the value between two patterns
awk -F'[=&]' '{print $2}' file
1234567890
sed command to print lines between two patterns
You can do it with awk: awk '/patt1/{flag=1}/patt2/{flag=0}flag' input_file
If input_file is:
111
222
333
444
555
awk '/222/{flag=1}/444/{flag=0}flag' input_file
gives:
222
333
Using sed to print lines between 2 patterns
I came up to this command
sed -n '1,/^Index:/{/^Index:/!d;}; /^Index:/{x;/^$/!p;n;n;}; H; ${g;p;};'
- It deletes from start till the first
Index:
line - Then it saves into a holding buffer everything from
Index:
till nextIndex:
excluding=======
line, which is assumed to followIndex:
immediately - When
Index:
line is met, it prints the content of the holding buffer if it's not empty When the end of the file reached it prints the content of the holding buffer
$ cat /tmp/test
First line
Index: <filepath>
===================================================================
<lines to print>
<lines to print>
<lines to print>
Index: <filepath>
===================================================================
<lines to print>
<lines to print>
<lines to print>
$ sed -n '1,/^Index:/{/^Index:/!d;}; /^Index:/{x;/^$/!p;n;n;}; H; ${g;p;};' \
/tmp/test
Index: <filepath>
<lines to print>
<lines to print>
<lines to print>
Index: <filepath>
<lines to print>
<lines to print>
<lines to print>But as David mentioned, it can be shorten and then it's just a simple
sed '1,/^Index:/{/^Index:/!d;}; /^=/d;' /tmp/test
which is just the same for lines before the first Index
and then just removing lines starting with =
Related Topics
How to Route Webcam Video to Virtual Video Device on Linux (Via Opencv)
Setting Environment Variable to a Large Value -> "Argument List Too Long"
How to Ask Bash for the Current Options
How to Do Like "Netstat -P", But Faster
Grep for String and Open at the Corresponding Line
Sed: Matching on 2 Patterns on the Same Line
How to Print Current Time in Kernel
Filter a Content File to Table
Linux C Socket: Blocked on Recv Call
Copying Files from Multiple Directories into a Single Destination Directory
How to Install Asp on Linux Ubuntu Hardy
Why Count Differs Between Ls and Ls -L Linux Command
Opening New Gnome-Terminal (V3.28+) with Multiple Tabs and Different Commands