1

In a Bash context I want to extract all text between two patterns that occur on different lines, but that don't constitute the entire line. So in particular I want to also print the text on the line where the patterns occur, but starting after the start pattern and ending before the stop pattern.

  • For example if the input looks like this:
    This is line 1
    Something else
    Line 3
    
  • and patterns are This and 3
  • Then desired output is:
    is line 1
    Something else
    Line
    
1
  • Please edit your question to add your requirements for the non-trivial cases (multiple sets of boundaries, nested boundaries, overlapping boundaries, start with no end, end with no start, start and end boundaries on the same line, etc., etc.) and update your sample input/output to be able to test those cases.
    – Ed Morton
    Mar 26, 2022 at 20:32

4 Answers 4

6

With GNU grep, Lookbehind (?<=This ) and Lookahead (?= 3):

grep -Poz '(?<=This )(.|\n)*(?= 3)' file

Output:

is line 1
Something else
Line

See: man grep and The Stack Overflow Regular Expressions FAQ

1
  • 2
    +1. Perhaps enabling (?s) the dot matcha by itself also \n ? I have tested and it works too. Mar 25, 2022 at 23:17
2

Perl to the rescue:

perl -0777 -ne 'BEGIN { ($f, $t) = (shift, shift) }
                /$f\s*(.*)\s*$t/s and print $1
               ' This 3 input.txt
  • -0777 turns on the "slurp mode", i.e. the whole file is read into memory and processed;
  • -n processes the input by the code;
  • At the beginning, the first two arguments are stored in the variables $f and $t;
  • If the input contains anything between the two patterns, it's stored in $1 and printed.
1

GNU sed in extended regex mode

sed -E '
  /This/,/3/ s/(^|\s+)(This|3)(\s+|$)//
' file

Assuming the search word This does not occur in something else text.

1
  • Note that this would destroy lines in-between the start and the end pattern that happen to also match the start pattern (if the middle line in the example had been This is something else, for example).
    – Kusalananda
    Mar 28 at 7:46
0

With sed:

$ cat file
This is line 1
This is Something else
Line 3
Line 33
This is more
data here
The 3rd bumblebee was never seen
$ sed -n '/.*This /,/ 3.*/ { s///; p; }' file
is line 1
This is Something else
Line
is more
data here
The

The sed editing script outputs sections of the input file. Each section starts with a line matching the start pattern .*This and ends with a line matching the end pattern 3.*. The script also removes the substring that matches the start pattern from the start line, and the substring that matches the end pattern from the end line.

Or,

$ sed -e '/.*This /,/ 3.*/!d' -e 's///' file
is line 1
This is Something else
Line
is more
data here
The

This has the same effect but is formulated differently. It removes the parts of the input that is not part of a section that we want, and trims the start and end lines of each section that we do want before outputting them.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .