1

From the many hits about searching a pattern and printing the lines until the end of the pattern, I've encountered an issue. The solution works if there is no other entry that is similar or has the common numbers in the pattern. Let me explain.

startpat=30.202.10.0  
endpat=31.202.10.0

inputfile is as follows:

30.202.10.0  
abcd  
efgh

31.202.10.0  
ijkl  
mnop

130.202.10.0  
qrst  
uvwx

awk -v startpat="${startpat}" -v endpat="${endpat}" '$0 ~ startpat{ x = 1} $0 ~ endpat{ x = 0}x' inputfile  

I get the expected output. The problem arises when the data contains as an example 130.202.10.0. The result contains lines

abcd  
efgh  

qrst  
uvwx  

How do I get as follows

abcd  
efgh  
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
Aires69
  • 87
  • 6
  • You should include lines like `31520251050` in your sample input/output as it's usually easy to match the text you want but much harder to not match similar text you don't want and that would let people test regexp vs string matching in addition to the full vs partial matching case you already have, `130.202.10.0`. See https://stackoverflow.com/q/65621325/1745001. – Ed Morton Jun 30 '23 at 10:59
  • Do some lines in your input **really** have trailing blank characters at the end like in your example? – Ed Morton Jun 30 '23 at 11:01

7 Answers7

2

Current code:

$ awk -v startpat="${startpat}" -v endpat="${endpat}" '$0 ~ startpat{ x = 1} $0 ~ endpat{ x = 0}x' inputfile  
30.202.10.0
abcd
efgh

130.202.10.0
qrst
uvwx

Assuming the patterns (startpat and endpat) are not to be printed, and blank lines are not to be printed, one awk idea:

$ awk -v startpat="${startpat}" -v endpat="${endpat}" '$1==startpat {x=1;next} $1==endpat {x=0;next} x && NF>0' inputfile
abcd
efgh
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
0

With SED :

startpat='30\.202\.10\.0'
endpat='31\.202\.10\.0'
sed -n -e "/^$startpat\$/!d; :loop; n; /^$endpat\$/d; p; b loop" INPUTFILE

Edited my answer to take into account Ed Morton's remark about dots matching any characters in the "startpat" / "endpat" variables. Thanks for pointing this out, I had totally overlooked that detail!

Grobu
  • 599
  • 1
  • 11
0

Using sed

$ sed -E "/\<${startpat//./\\.}\>/,/\<${endpat//./\\.}\>|^$/!d;//d" input_file
abcd
efgh

Edited my answer to take into account Ed Morton's remark about dots matching any characters in the "startpat" / "endpat" variables. Thanks for pointing this out, I had totally overlooked that detail!

Grobu
  • 599
  • 1
  • 11
HatLess
  • 10,622
  • 5
  • 14
  • 32
0

Using any awk handling 1 line at a time:

$ awk -v beg="$startpat" -v end="$endpat" '$1==end{f=0} f; $1==beg{f=1}' inputfile
abcd
efgh

or if you prefer to treat the input as empty-line-separated multi-line records:

$ awk -v beg="$startpat" -v end="$endpat" -v RS= -v ORS='\n\n' '$1==beg{f=1} $1==end{f=0} f{sub(/[^\n]+\n/,""); print}' inputfile
abcd
efgh

The above do full-string matching and so won't falsely match on substrings or regexp metachars. I'm testing for $1 instead of $0 to handle the trailing blanks in your input.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

This might work for you (GNU sed):

sed -nE '/^30\.202\.10\.0/{:a;n;/^31\.202\.10\.0/bb;/\S/H;ba;:b;g;s/.//p;z;x}' file

Match 30\.202\.10\.0 then collect further lines until another match of 31\.202\.10\.0 (dropping the first and last lines and only storing non-empty lines).

Remove an introduced starting newline and print the result.

Clean up ready for another match.

N.B. This solution remove empty lines, if all lines empty or not are required, use:

sed -nE '/^30\.202\.10\.0/{:a;n;/^31\.202\.10\.0/bb;H;ba;:b;g;s/.//p;z;x}' file
potong
  • 55,640
  • 6
  • 51
  • 83
0
startpat="30.202.10.0"  
endpat="31.202.10.0"

awk -v startpat="${startpat}" -v endpat="${endpat}" '
    BEGIN{gsub(/\./, "\\.", startpat); gsub(/\./, "\\.", endpat)}
    match($0, "^"startpat" *$"){
        found=1
        next
    }
    match($0, "^"endpat" *$"){
        exit
    }
    found && !/^$/
' file

abcd  
efgh
ufopilot
  • 3,269
  • 2
  • 10
  • 12
0

For pattern matching stuffs, perl is highly flexible & right choice. In Perl, using file slurp mode. Assuming the file content is available in aires.txt

perl -0777 -ne ' $start="30.202.10.0"; $end="31.202.10.0"; print $1 if m/$start(.+?)$end/s ' aires.txt

abcd  
efgh
stack0114106
  • 8,534
  • 3
  • 13
  • 38