Possible Duplicate:
How can I search for a multiline pattern in a file ? Use pcregrep
I'm running a grep
to find any *.sql file that has the word select
followed by the word customerName
followed by the word from
. This select statement can span many lines and can contain tabs and newlines.
I've tried a few variations on the following:
$ grep -liIr --include="*.sql" --exclude-dir="\.svn*" --regexp="select[a-zA-Z0-
9+\n\r]*customerName[a-zA-Z0-9+\n\r]*from"
This, however, just runs forever. Can anyone help me with the correct syntax please?
Without the need to install the grep variant pcregrep, you can do multiline search with grep.
Explanation:
-P
activate perl-regexp for grep (a powerful extension of regular extensions)-z
suppress newline at the end of line, subtituting it for null character. That is, grep knows where end of line is, but sees the input as one big line.-o
print only matching. Because we're using-z
, the whole file is like a single big line, so if there is a match, the entire file would be printed; this way it won't do that.In regexp:
(?s)
activatePCRE_DOTALL
, which means that.
finds any character or newline\N
find anything except newline, even withPCRE_DOTALL
activated.*?
find.
in nongreedy mode, that is, stops as soon as possible.^
find start of line\1
backreference to first group (\s*
) This is a try to find same indentation of methodAs you can imagine, this search prints the main method in a C (
*.c
) source file.Your fundamental problem is that
grep
works one line at a time - so it cannot find a SELECT statement spread across lines.Your second problem is that the regex you are using doesn't deal with the complexity of what can appear between SELECT and FROM - in particular, it omits commas, full stops (periods) and blanks, but also quotes and anything that can be inside a quoted string.
I would likely go with a Perl-based solution, having Perl read 'paragraphs' at a time and applying a regex to that. The downside is having to deal with the recursive search - there are modules to do that, of course, including the core module File::Find.
In outline, for a single file:
That needs to be wrapped into a sub that is then invoked by the methods of File::Find.
I am not very good in grep. But your problem can be solved using AWK command. Just see
The above code will result from first occurence of
select
till first sequence offrom
. Now you need to verify whether returned statements are havingcustomername
or not. For this you can pipe the result. And can use awk or grep again.