简体   繁体   中英

SED or AWK command to print only lines that are between two set patterns

I need a command / script to get the CVS merge conflicts. Basically, I need a SED or AWK command to print only lines that are between the two set patterns

Example:

Pattern1="RCS file:"
Pattern2="conflicts during merge"

When I try a simple SED command like:

sed -n '/RCS file:/,/conflicts during merge /p' INPUT.txt

I am not getting the expected output. I want to capture the details for "filename2 and filename3" only (which had conflicts during merge).

Can someone please help?

INPUT.txt

RCS file: /hello/filename1
retrieving revision 1.4.2.1.18.2.2.1
retrieving revision 1.4.2.1.18.2.2.1.4.2
Merging differences between 1.4.2.1.18.2.2.1 and 1.4.2.1.18.2.2.1.4.2 into filename1

RCS file: /hello/filename2
retrieving revision 1.4.2.1.18.2.2.1
retrieving revision 1.4.2.1.18.2.2.1.4.2
Merging differences between 1.4.2.1.18.2.2.1 and 1.4.2.1.18.2.2.1.4.2 into filename2
rcsmerge: warning: conflicts during merge

RCS file: /hello/filename3
retrieving revision 1.6.18.1.2.1.2.1
retrieving revision 1.6.18.1.2.1.2.1.4.3
Merging differences between 1.6.18.1.2.1.2.1 and 1.6.18.1.2.1.2.1.4.3 into filename3
rcsmerge: warning: conflicts during merge

RCS file: /hello/filename4
retrieving revision 1.4.2.1.18.2.2.1
retrieving revision 1.4.2.1.18.2.2.1.4.2
Merging differences between 1.4.2.1.18.2.2.1 and 1.4.2.1.18.2.2.1.4.2 into filename4

(Expected) OUTPUT.txt

RCS file: /hello/filename2
retrieving revision 1.4.2.1.18.2.2.1
retrieving revision 1.4.2.1.18.2.2.1.4.2
Merging differences between 1.4.2.1.18.2.2.1 and 1.4.2.1.18.2.2.1.4.2 into filename2
rcsmerge: warning: conflicts during merge

RCS file: /hello/filename3
retrieving revision 1.6.18.1.2.1.2.1
retrieving revision 1.6.18.1.2.1.2.1.4.3
Merging differences between 1.6.18.1.2.1.2.1 and 1.6.18.1.2.1.2.1.4.3 into filename3
rcsmerge: warning: conflicts during merge

Your sed command is starting to output whenever it sees 'RCS file' and stops when it sees the 'conflicts' marker. So it pretty much outputs everything. It's possible to do what you want with sed, but it's complicated. Awk is much simpler:

awk -v RS= '/conflicts/ {print $0}' INPUT.txt 

Use awk's notion of records with a blank line separating them, and essentially grep each record. So this doesn't print lines between two patterns, rather it prints each block of lines that matches a particular pattern.

Here you have a hint:

awk '{if ($1=="HO") i=1}; {if ($1=="JOU") i=0}; i{print}' file

Example:

$ cat file
HI
HO
JE
JOU
LA

So,

Pattern1="HO"
Pattern2="JOU"
awk -v p1=${Pattern1} -v p2=${Pattern2} '{if ($1==p1) i=1}; {if ($1==p2) i=0}; i{print}' file
HO
JE

Based on your case,

Pattern1="RCS file:"
Pattern2="conflicts during merge"

$ awk -v p1=$(Pattern1) -v p2=${Pattern2} '{if ($1==p1) i=1}; {if ($1==p2) i=0}; i{print}' file

Edit

If you want to look for the string containing this text, you can do it like this:

Pattern1="RCS file:"
Pattern2="conflicts during merge"

$ awk -v p1=$(Pattern1) -v p2=${Pattern2} '{if ($1 ~ p1) i=1}; {if ($1 ~ p2) i=0}; i{print}' file

Bro ,

use egrep ..... its simple , no need to worry on SED and AWK. Its a fixed pattern of lines that you want here ....

 egrep +B4 conflict INPUT.txt   

here B option prints the 4 lines before the match along with the line that matches the pattern ( im using GNU egrep)

egrep output :

RCS file: /hello/filename2
retrieving revision 1.4.2.1.18.2.2.1
retrieving revision 1.4.2.1.18.2.2.1.4.2
Merging differences between 1.4.2.1.18.2.2.1 and 1.4.2.1.18.2.2.1.4.2 into filename2
rcsmerge: warning: conflicts during merge
--
RCS file: /hello/filename3
retrieving revision 1.6.18.1.2.1.2.1
retrieving revision 1.6.18.1.2.1.2.1.4.3
Merging differences between 1.6.18.1.2.1.2.1 and 1.6.18.1.2.1.2.1.4.3 into filename3
rcsmerge: warning: conflicts during merge

Here you go:

sed -n '/RCS file:/ !{H;d}; /RCS file:/ {x; /conflict/p}; $ {x; /conflict/p}' input.txt

For every line that doesn't match 'RCS file:' - append it to hold space. If it matches the line (or is the end of file) - swap the pattern space with hold space and check if it matches 'conflit'. Print if it does.

Could be simpler if we use branching.

Like this:

sed -n '$ba; /RCS file:/ba; H; d; :a; x; /conflict/p' input.txt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM