如何使用 ag 或 rg(PCRE/Rust 正则表达式)匹配不同行中包含 word1 和 word2 的所有文件

how to match all files containing word1 AND word2 across different lines with ag or rg (PCRE/Rust regex)

我有一长串要过滤的已生成报告。报告是这样的:

Report Name
Report Date
Blah blah blah
Blah: WORD1
Blah blah
blah blah: WORD2
blah blah

我正在尝试使用 ag(PCRE 正则表达式)或 rg(rust 正则表达式)并在文件的不同位置(包含新行)查找包含 WORD1 和 WORD2 的所有文件。

我已经搜索过 SX,发现这些都不起作用:

> ag (?=.*WORD1)(?=.*WORD2)

> ag (?=.*WORD1)((.|\n)*)(?=.*WORD2)

更新

正如@WiktorStribiżew 所指出的,ag 使用 PCRE。抱歉弄错了。

我的预期输出是:

blah blah: WORD2

或者只是匹配文件的列表。


p.s。目前我已经设法使用这个:

> ag "WORD2" $(ag -l "WORD1")

您可以使用 ag:

的 PCRE 模式
(?s)^(?=.*WORD1)(?=.*WORD2).*\n\K(?-s).*WORD2

参见regex demo

详情:

  • (?s) - DOTALL 修饰符开启(. 匹配换行字符)
  • ^ - 字符串开头
  • (?=.*WORD1) - 字符串中某处必须有 WORD1
  • (?=.*WORD2) - 字符串中某处必须有 WORD2
  • .* - 任何 0+ 个字符,尽可能多,直到后续子模式的最后一次出现(如果使用惰性 *? 量词,.*? 将匹配0+ 个字符尽可能少,直到 first 出现后续子模式)
  • \n - 一个换行符
  • \K - 匹配重置运算符丢弃当前匹配的文本
  • (?-s) - DOTALL 模式禁用(. 不匹配换行符)
  • .*WORD2 - 除换行字符外的任何 0+ 个字符,尽可能多,然后是 WORD2.

p.s. currently I've managed to using this: ag "WORD2" $(ag -l "WORD1")

这当然是最简单的方法。您正在谈论的工具本质上是面向行的,您希望匹配同一文件中的不同行。

如果你使用 ack,它有 -x 运算符,可以让你做 ack -l WORD1 | ack -x WORD2 这基本上与 ack -l WORD1 | xargs ack WORD2 相同,而不必将 xargs 引入管道。

问题提到了这个模式,有效:

ag "WORD2" $(ag -l "WORD1")

但只有 WORD2 会以颜色突出显示。我更喜欢:

ag 'WORD1|WORD2' --passthru -C3 $(ag -l "WORD1" $(ag -l "WORD2"))

这会在匹配项的两侧给出三行,并突出显示 WORD1WORD2

function agmw() {
  args=("$@")
  qs="ag -l  "
  for i in {2..$#}; do
    qs="$qs | xargs -r ag -l '${args[$i]}'"
  done
  argarr=""
  for i in {2..$#}; do
    argarr="$argarr|${args[$i]}"
  done
  qs="$qs | xargs -r ag '$argarr'"
  echo $qs
  ag '$argarr'
  bash -c $qs
}

agmw hello world #seacrh hello and world 所有文​​件