【问题标题】:grep or ripgrep: How to find only files that match multiple patterns (not only on the same line)?grep 或 ripgrep:如何仅查找与多个模式匹配的文件(不仅在同一行上)?
【发布时间】:2019-11-26 14:04:44
【问题描述】:

我正在寻找一种快速方法来查找文件夹中包含 2 个或更多模式的所有文件

grep -l -e foo -e bar ./* 或者 rg -l -e foo -e bar

在同一行中显示所有包含“foo”和“bar”的文件,或者在不同行中显示包含“foo”或“bar”的所有文件,但我只想要至少有一个“foo”匹配和一个“bar”匹配的文件在不同的行。只有 'foo' 匹配或只有 'bar' 匹配的文件将被过滤掉。

我知道我可以链接 grep 调用,但这太慢了。

【问题讨论】:

    标签: grep ripgrep


    【解决方案1】:
    $ cat f1
    afoot
    2bar
    $ cat f2
    foo bar
    $ cat f3
    foot
    $ cat f4
    bar
    $ cat f5
    barred
    123
    foo3
    
    $ rg -Ul '(?s)foo.*?\n.*?bar|bar.*?\n.*?foo'
    f5
    f1
    

    您可以使用-U 选项跨行匹配。 s 标志将使. 也能匹配换行符。由于您希望匹配跨越不同的行,因此您还需要在搜索词之间匹配换行符。

    【讨论】:

      【解决方案2】:

      如果要搜索出现在多行的两个或多个单词,除了提供-U/--multiline 之外,还可以使用ripgrep 的选项--multiline-dotall。您还需要使用| 运算符在bar 之前搜索foo 和在foo 之前搜索bar

      rg -lU --multiline-dotall 'foo.*bar|bar.*foo' .
      

      对于任意数量的单词,您需要| 这些单词的所有排列。为此,我使用了一个小的 python 脚本(我称之为rga),它在 当前目录(和向下),用于包含命令行中给出的所有参数的文件:

      #! /opt/util/py310/bin/python
      
      import sys
      import subprocess
      from itertools import permutations
      
      rgarg = '|'.join(('.*'.join(x) for x in permutations(sys.argv[1:])))
      cmd = ['rg', '-lU', '--multiline-dotall', rgarg, '.']
      # print(' '.join(cmd))
      proc = subprocess.run(cmd, capture_output=True)
      sys.stdout.write(proc.stdout.decode('utf-8'))
      

      我已经成功搜索了六个参数,命令行变得很长。通过将参数保存到文件并添加 -f file_name 可能有解决此问题的方法,但我从未需要/调查过。

      【讨论】:

        【解决方案3】:

        所以这并不能完美地回答这个问题,但是,这是我每次谷歌“ripgrep 多种模式”时弹出的 StackOverflow 问题。所以我把我的答案留给未来的谷歌人(包括我自己)......

        我主要在 PowerShell 中工作,所以这就是我在 PowerShell 的 ripgrep 中执行and 搜索的方式。这将匹配相同的行匹配,这就是为什么它不是一个完美的答案,但它会识别匹配两种模式的文件,并且运行相对较快:

        rg -l 'SecondSearchPattern' (rg -l 'FirstSearchPattern')
        

        解释:

        • 首先运行括号:rg -l 'FirstSearchPattern',它会在所有文件中搜索模式 FirstSearchPattern。通过使用-l,它只返回一个文件路径列表。

        • 通过将它放在(parentheses) 中,它首先运行整个命令,然后将命令的结果“splats”到外部rg 命令中。

        • 外部rg 命令现在运行如下:

          rg -l 'SecondSearchPattern' "file.txt" "directory\file.txt"

          是的,它确实将它们放在引号中,因此它处理带有空格的路径。这将搜索与模式 SecondSearchPattern 匹配的所有提供的文件。因此只返回匹配两种模式的文件。

        您可以更进一步,添加| Get-Item (| gi) 以返回文件系统对象,并添加| % FullName 以获取完整路径。

        rg -l 'SecondSearchPattern' (rg -l 'FirstSearchPattern') | gi | % FullName
        

        【讨论】:

          【解决方案4】:

          rgmultiline 确实有效,但它会打印出标准之间的所有内容,有时这没有用。

          对于链接搜索的用例(例如html, json 等),其中第一个标准只是缩小文件范围,而第二个标准实际上是我正在寻找的,这是一个可能的解决方案:

          rg -0 -l crit1 | xargs -0 -I % rg -H crit2 %
          

          另外,我刚刚发现 ugrep 支持在 linefile 级别使用布尔运算符组合多个条件。这是相当的事情。它比rg + xargs 慢一点,但是它可以很好地打印符合文件中所有条件的所有行(而不是只显示上面的最后一个条件):

          ugrep --files -e crit1 --and -e crit2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多