1

To be precise

Some text
begin
Some text goes here.
end
Some more text

and I want to extract entire block that starts from "begin" till "end"

with awk we can do like

awk '/begin/,/end/' text

how to do with grep? Are there any grep implementations on some *nix with which it can be done?

7
  • For such kind of operation better to use sed same with awk: sed '/begin/,/end/! d' text
    – Costas
    Commented Nov 19, 2014 at 9:36
  • Yes, with awk, sed it is possible. But that can't be done using grep?
    – Iker
    Commented Nov 19, 2014 at 9:38
  • @slm, what's the point of closing the question for that reason? This question makes sense on both sites (askubuntu and here), a lot more so on unix.se Commented Nov 19, 2014 at 12:07
  • @StéphaneChazelas - we have a specific close reason b/c cross-posting isn't allowed/tolerated. It's one thing if the Q was modified to conform to each site, but in this case it was a verbatim copy/paste. It's just not allowed. If the OP wants to close/delete the other Q's then it can be reopened. BTW, it was specifically flagged by others and I handled the flagging.
    – slm
    Commented Nov 19, 2014 at 12:17
  • 2
    don't crosspost askubuntu.com/questions/551338/… Commented Nov 19, 2014 at 15:53

1 Answer 1

7

grep, that is g/re/p is a basic tool to print the lines that match a regular expression.

You want more here like a stream editor:

sed '/^begin$/,/^end$/!d'

or a more general text processing tool with an advanced language like awk, perl... as you already found out.

Having said that, some grep implementations can go a little further.

pcregrep -M '(?s)^begin$.*?^end$'

That's using the multi-line mode (-M); (?s) toggles the s flag in PCRE regexp so that . also matches newline characters.

With the current version of pcregrep, it's not guaranteed to work if the begin and end are more than 20kiB apart (or the specified buffer size).

For instance, it will match in

(seq 12091; echo begin; seq 4315; echo end; seq 10) |
   pcregrep -M '(?s)^begin$.*?^end$'

But not in:

(seq 12091; echo begin; seq 4316; echo end; seq 10) |
   pcregrep -M '(?s)^begin$.*?^end$'

Or with GNU grep built with PCRE support and assuming the file doesn't contain NUL characters:

grep -zoP  '(?ms)^begin$.*?^end$'

However that means that grep will load the entire file in memory before starting the search so should not be used except for small files. It also appends a NUL character to the output.

In any case, grep is not the right way to go here.

You must log in to answer this question.

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