Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How do I search for a phrase over multiple lines? E.g. Lets have the phrase "my ice tea" then it may be wrapped in text files:

as js skdfh dfh djh sf my
ice tea.

grep will not match since there is a newline in between. How do I match those? Another multiline pattern would be pattern1_\n_pattern2

I know the easiest way I do ATM is just grep for one part e.g. just ice with -A2 -B2 flag and then in that output againg for e.g. tea. But this is very tedious. So I am interessted on how do you would solve this.

share|improve this question

3 Answers 3

up vote 11 down vote accepted

You could install pcregrep (available in most distro repositories) - which is grep using the pcre library, which does "Perl Compatible Regular Expressions". It has a command line option -M which allows you to do multiline searches - from the man page:

"The output for any one match may consist of more than one line."

So you could do

pcregrep -M 'my\s+ice\s+tea' filename

The \s is whitespace, which will match \n and \r in multiline mode, in addition to the normal whitespace characters. You can also match the newline character directly, so you could do

pcregrep -M 'pattern1_\n_pattern2' filename
share|improve this answer
    
+1 nice. never heard of it, but tried it and it works like a charm! –  DaveParillo Jul 20 '10 at 15:38
    
Doesn't grep -E do pcre patterns? –  Daenyth Jul 20 '10 at 17:40
1  
@Daenyth grep -E mostly just means you can use ?, +, {, |, (, and ) as their usual regex meaning without having to have a \ in front, as you do if you use standard grep. So grep 'hello\s\+world' file is equivalent to grep -E 'hello\s+world' file. It doesn't do PCRE. There is grep -P for perl regular expressions, but it is experimental (according to the man page) and I think it is a little different from pcregrep ... –  Hamish Downer Jul 20 '10 at 21:17
    
Yes, I was thinking of -P when I said -E, but I didn't realize it was different. –  Daenyth Jul 21 '10 at 2:31

I would probably do a search using vim's :vimgrep command. This works in a manner vaguely similar to that of grep but supports vim REs and paths.

Basically you run something like :vimgrep 'pattern1\npattern2' path/** for a recursive search, then type :copen to bring up a smaller window containing a list of matches.

vim REs can do mostly everything that PCREs can, but they evolved separately from the perl regular expression lineage so most of the advanced stuff works differently. Their basic functionality is more like that of basic REs, but they have some nifty additions that PCREs don't offer.

I'm not sure if it's possible to get :vimgrep to spit out data as grep does; I've only ever tried to use it for navigation within vim.

:help vimgrep from within vim for more info; :help pattern.txt for info on vim REs; for more info on paths see :help wildcards.

share|improve this answer
    
Be careful -- that's not entirely portable as it will behave differently on different platforms –  Daenyth Jul 20 '10 at 17:41
    
@Daenyth: do you mean under the influence of different .vimrc's? It should be more portable than grep with respect to the operating system: vim doesn't have a "POSIX flavour", and works more or less identically even under Windows. ............................................................................. It's possible to add qualifiers to ensure that e.g. the right amount of "magic" gets used on the RE, though as I understand it there is a strict unwritten rule to leave that option the heck alone. –  intuited Jul 21 '10 at 4:55
    
I haven't used it myself, but apparantly it uses a different backend on windows (find.exe instead of grep). There was another question within the last few weeks that had that issue. –  Daenyth Jul 21 '10 at 13:01
1  
@Daenyth: Are you thinking of :vimgrep or :grep? From :help grep: "The advantage of the internal grep [i.e. :vimgrep] is that it works on all systems and uses the powerful Vim search patterns." –  intuited Jul 21 '10 at 13:35
1  
Ah, that must be it. I got the two confused. –  Daenyth Jul 21 '10 at 15:36

Grep only works on one line at a time, but you could use awk to print lines matching a range of patterns:

cat file | awk '/foo/,/bar/'

it would match anything, not just newlines between the two patterns

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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