正则expression式(grep)用于多行search需要

可能重复:
如何在文件中search多行模式? 使用pcregrep

我正在运行一个grep来查找任何* .sql文件,它包含单词select后跟单词customerName后跟单词from 。 这个select语句可以跨越多行,可以包含制表符和换行符。

我已经尝试了以下几个变化:

 $ grep -liIr --include="*.sql" --exclude-dir="\.svn*" --regexp="select[a-zA-Z0- 9+\n\r]*customerName[a-zA-Z0-9+\n\r]*from" 

然而,这只是永远运行。 任何人都可以帮助我正确的语法吗?

不需要安装grep变种pcregrep,你可以用grep进行多行search。

 $ grep -Pzo "(?s)^(\s*)\N*main.*?{.*?^\1}" *.c 

说明:

-P为grep激活perl-regexp(常规扩展的强大扩展)

-z在行尾抑制换行符,将其replace为空字符。 也就是说,grep知道行尾是什么,但是看到input是一条大行。

-o只打印匹配。 因为我们使用的是-z ,整个文件就像是一个大行,所以如果匹配,整个文件将被打印。 这样它不会那样做。

在正则expression式中:

(?s)激活PCRE_DOTALL ,这意味着. find任何字符或换行符

\Nfind除了换行符之外的任何内容,即使PCRE_DOTALL激活

.*? find. 在nongreedy模式下,即尽快停止。

^find线的开始

\1反向引用第一组( \s* )这是尝试find相同的缩进方法

你可以想象,这个search在C( *.c )源文件中打印主要的方法。

我在grep上不是很好。 但是你的问题可以使用AWK命令来解决。 看看

 awk '/select/,/from/' *.sql 

上面的代码将从第一次发生直到从第一个序列from 。 现在您需要validation返回的语句是否具有customername 。 为此,您可以输出结果。 并可以再次使用awk或grep。

你的根本问题是, grep一次只能处理一行 – 所以找不到跨行的SELECT语句。

你的第二个问题是,你正在使用的正则expression式并不处理在SELECT和FROM之间可能出现的复杂性 – 特别是它省略了逗号,句号(句号)和空格,还有引号和任何可以在里面一个引用的string。

我可能会使用基于Perl的解决scheme,让Perl每次读取“段落”,并应用一个正则expression式。 缺点是不得不处理recursionsearch – 当然有模块可以做到这一点,包括核心模块File :: Find 。

总的来说,对于单个文件:

 $/ = "\n\n"; # Paragraphs while (<>) { if ($_ =~ m/SELECT.*customerName.*FROM/mi) { printf file name go to next file } } 

这需要被包装成一个子然后由File :: Find的方法调用。

除了正则expression式,你可能想看看ack ,它会自动排除你的.svn目录,哪些只能使用–sql来限制.sql文件。