I am on Ubuntu 16.04 and I want to search files for let’s say “if” and I want to the output until “endif”. The file could look like this

if …

I can do this with grep -A9 if my_file | grep -B9 endif. This doesn’t works if the “if” clause is larger than 9 and if several “if” clauses are in the same file and if the first grep command contains several “if” clauses. The option -m1 in the second grep doesn’t help. Nested “if” clauses can be ignored. Has somebody an idea, maybe not with grep?

Difference to How do I grep for multiple patterns on multiple lines?

  1. The question asks for a solution with grep which is answered already in the question: grep -A9 if my_file | grep -B9 endif. The solution doesn’t work in my case but would work in the case of the other question.

  2. The proposed grep solutions of the other question don’t work (with Ubuntu?): grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstützt. which is something like grep: a not protected ^ or $ is not supported with -Pz. I use the following:

    root:/tmp# cat file
    Some text
    Some text goes here.  
    Some more text 
    root:/tmp# grep -Pzo "^begin\$(.|\n)*^end$" file
    grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstützt
  3. The proposed solutions search only for pattern which start at the beginning of the line if I interpret the proposed solution correctly. Even if I remove ^ the command doesn't work.

  • About 2: Show us what pattern you used with grep -Pz. 3. What is a "pure Linux solution"? 4. grep can look anywhere in the line.
    – muru
    Nov 14 '16 at 1:57
  • 2) You can edit your post, as you very well know. 3) LOL, Perl is not a secondary package by a long shot. It's as likely to be present on any Linux system as grep or sed. 4) So you know what ^ does.
    – muru
    Nov 15 '16 at 1:13
  • 2) The trick was to put 8 (!) blanks in front because it is inside of a numbering. 3) I refer to the pcregrep and so on of the answer of steeldriver. But it is a matter of tasked, as I said. Anyway I have taken it out. 3) Yes, but even without ^ it doesn’t work.
    – musbach
    Nov 15 '16 at 7:59
  • 1
    The title doesn't fit the question: it should be Show lines between two patterns. Whoever wants lines from the first line on, doesn't get his answer here
    – Bilow
    Dec 12 '18 at 13:08

You can use sed for that:

sed -n '/if/,/endif/p' myfile
  • -n don't print anything until we ask for it
  • /if/ find the first line with this
  • , keep going until...
  • /endif/ this is the last line we want
  • p print the matched lines
  • 2
    Indeed, sed or (better!) awk are precisely the tools for this, as standard programs that have built-in begin/end pattern matching. Nov 13 '16 at 19:54
  • @Zanna, What should be in place of "," if I want to keep going up in the text, not down? Mar 31 '19 at 7:03
  • @JosefKlimuk I am not aware of a way. Can only suggest you put the top pattern or first line number you want to match first without further info. You could ask a question with details of your use case :)
    – Zanna
    Mar 31 '19 at 7:57
  • @Zanna, "Can only suggest you put the top pattern or first line number you want to match first without further info". Simple and good. Thanks Mar 31 '19 at 8:01

Traditional grep is line-oriented. To do multiline matches, you either need to fool it into slurping the whole file by telling it that your input is null terminated e.g.

grep -zPo '(?s)\nif.*\nendif' file

or use a more flexible tool such as pcregrep

pcregrep -M '(?s)\nif.*?\nendif' file

or perl itself

perl -00 -ne 'print if m/^if.*?endif/s' file

Alternatively, for matching structured input in a grep-like way, there's sgrep

sgrep '"if" .. ("endif") containing "SOME CODE"' file
  • 2
    AFAIK, trying to fool grep et al. by specifying a nonexistent (or even just very rare) terminator is inherently brittle and non-portable, due to limited line buffer sizes in various implementations. IIRC one does not need to worry much if using the GNU versions, but not everyone does that. Anyway, it seems to me that sed or awk are far better suited to this sort of task than non-standard extended greps or perl: both seem too complex for a simple "sed 101" question like this, and extended greps are probably equally non-portable. Nov 13 '16 at 19:50
  • @underscore_d this site is about Ubuntu, so portability isn't really an issue. And learning more about what grep, or any other tool, can do is always a good thing (even if just for fun) isn't it?
    – Zanna
    Nov 13 '16 at 20:19
  • @Zanna I didn't even notice this was Ask Ubuntu... all of SE blurs together some days. :D But it's not unreasonable to suppose that enough people who happen to use Ubuntu might be interested in writing portable shell. And sure, don't get me wrong, I think this answer is useful by showing how this could be done with some forms of grep, but just wanted to note some (if theoretical) limitations and alternatives. Nov 13 '16 at 23:12

A solution awk could look like: awk '/if/,/endif/' file

Of course, it is similar to the solution with sed.

  • 4
    Yes, this works as well. One difference is between the sed and awk solution: If I replace file by * I get different results. sed seems to search only for ascii files(?) and awk includes binary files as well.
    – musbach
    Nov 14 '16 at 7:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.