linux 需要正则表达式(grep)进行多行搜索[重复]

htzpubme  于 2023-11-17  发布在  Linux
关注(0)|答案(3)|浏览(177)

此问题在此处已有答案

How can I search for a multiline pattern in a file?(13个回答)
两年前关闭。
我正在运行一个grep来查找任何包含单词select、单词customerName和单词from的 *.sql文件。这个select语句可以跨很多行,并且可以包含制表符和换行符。
我尝试了以下几种变化:

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

字符串
然而,这只是永远运行。有人能帮助我正确的语法吗?

guykilcj

guykilcj1#

不需要安装grep变体pcregrep,您可以使用grep进行多行搜索。

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

字符串
说明:
-P为grep激活perl-regexp(正则表达式的强大扩展)
-z将输入视为一组行,每行以零字节(ASCII NUL字符)而不是换行符结束。也就是说,grep知道行的结尾在哪里,但将输入视为一个大行。注意,如果与-o一起使用,这也会添加一个尾随NUL字符,请参阅注解。
-o只打印匹配项。因为我们使用的是-z,所以整个文件就像一个大行,所以如果有匹配项,整个文件就会被打印出来;这样就不会这样做了。
在regexp中:
(?s)激活PCRE_DOTALL,这意味着.查找任何字符或换行符
\N查找除换行符以外的任何内容,即使激活了PCRE_DOTALL
.*?在非贪婪模式下查找.,即尽快停止。
^查找行首
\1反向引用到第一组(\s*)。这是一个尝试寻找相同缩进的方法。
可以想象,这个搜索将打印C(*.c)源文件中的main方法。

展开查看全部
sshcrbum

sshcrbum2#

我不是很擅长grep。但是你的问题可以用AWK命令解决。看看

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

字符串
上面的代码将从第一次出现select到第一个from序列产生。现在你需要验证返回的语句是否有customername。为此,你可以管道结果。并且可以再次使用awk或grep。

4sup72z8

4sup72z83#

您的根本问题是grep一次只能运行一行--因此它无法找到跨行分布的SELECT语句。
你的第二个问题是,你使用的正则表达式没有处理SELECT和FROM之间可能出现的复杂性-特别是,它省略了逗号,句号(句号)和空格,但也省略了引号和任何可以在引号字符串中出现的东西。
我可能会使用基于Perl的解决方案,让Perl一次读取“段落”,并对其应用正则表达式。缺点是必须处理递归搜索-当然,有模块可以做到这一点,包括核心模块File::Find
概括地说,对于单个文件:

  1. $/ = "\n\n"; # Paragraphs
  2. while (<>)
  3. {
  4. if ($_ =~ m/SELECT.*customerName.*FROM/mi)
  5. {
  6. printf file name
  7. go to next file
  8. }
  9. }

字符串
它需要被 Package 到一个sub中,然后由File::Find的方法调用。

展开查看全部

相关问题