【问题标题】:Find files containing multiple strings查找包含多个字符串的文件
【发布时间】:2017-02-12 12:33:55
【问题描述】:

我使用命令递归查找包含某个string1的文件:

find . -type f -exec grep -H string1 {} \;

我需要查找包含多个字符串的文件,因此该命令应返回包含所有字符串的文件。像这样的:

find . -type f -exec grep -H string1 AND string2 {} \;

我找不到方法。字符串可以在文件中的任何位置。即使只有两个字符串的解决方案也会很好。

【问题讨论】:

  • 我可以将您的问题转换为“egrep”问题:命令egrep -l "string1|string2" 给出包含string1string2 的所有文件,以防存在参数以使@987654327 @give 包含string1string2 的文件,您的问题将得到解决。 (不过我不知道这样的参数是否存在)
  • 理论上可以有一个联合运算符& 就像| 对应于交集,但没有常见的正则表达式工具实现这一点。简单的解决方法是awk '/pattern1/ && /pattern2/',所以已经有一种简单的方法可以做到这一点,尽管grep 没有。

标签: string unix search grep find


【解决方案1】:

惊讶于这个老问题缺少明显简单的 Awk 解决方案:

find . -type f -exec awk '/string1/ && /string2/ { print; r=1 } END { exit 1-r }' {} \;

r 变量的诡计只是模拟来自grep 的退出代码(零表示找到,一表示未找到;如果您不在乎,可以将其取出)。

为了提高效率,也许从-exec ... {} \; 切换到-exec ... {} + 虽然你可能想稍微重构一下 Awk 脚本(要么扔掉退出代码,要么更改退出代码以使退出代码指示类似“没有匹配的文件" vs "只有部分文件匹配" vs "所有文件匹配"?)

【讨论】:

    【解决方案2】:

    您可以链接您的操作并使用第一个操作的退出状态仅在第一个操作成功时执行第二个操作。 (省略主节点之间的运算符默认为-and/-a。)

    find . -type f -exec grep -q 'string1' {} \; -exec grep -H 'string2' {} \;
    

    第一个 grep 命令使用-q,“quiet”,如果找到字符串,则返回成功退出状态。

    【讨论】:

      【解决方案3】:

      回答

      您可以从本页的其他答案中看到,有几个命令行工具可用于跨文件执行连接搜索。一个尚未发布的快速灵活的解决方案是使用ag

      ag -l string1 | xargs ag -l string2
      

      有用的变体

      对于不区分大小写的搜索,使用ag-i 选项:

      ag -il string1 | xargs ag -il string2
      

      对于其他搜索词,扩展管道:

      ag -l string1 | xargs ag -l string2 | xargs ag -l string3 | xargs ag -l string4
      

      【讨论】:

        【解决方案4】:

        使用 GNU grep

        grep -rlZ 'string1' | xargs -0 grep -l 'string2'
        


        来自man grep

        -r, --recursive

        递归读取每个目录下的所有文件,遵循符号 仅当它们在命令行上时才链接。请注意,如果没有文件 给定操作数,grep 搜索工作目录。这是 相当于 -d 递归选项。

        -Z, --null 输出一个零字节(ASCII NUL 字符)而不是通常跟在文件后面的字符 姓名。例如, grep -lZ 在每个文件名之后输出一个零字节,而不是通常的换行符。 此选项使输出明确,即使存在包含异常的文件名 换行符之类的字符。此选项可与 find -print0、perl -0、sort -z、 和 xargs -0 来处理任意文件名,即使是那些包含换行符的文件。

        【讨论】:

          【解决方案5】:

          你也可以试试这个;

          find . -type f -exec grep -l 'string1' {} \; | xargs grep -l 'string2'
          

          这显示了包含 string1 和 string2 的文件名

          【讨论】:

          • 这是一个非常好的解决方案。我建议用单引号将{} 括起来,并使用xargs-d 参数来避免由于带有空格的文件名而导致的错误,例如:find . -type f -exec grep -l 'string1' '{}' \; | xargs -d '\n' grep -l 'string2'
          猜你喜欢
          • 1970-01-01
          • 2014-05-25
          • 2016-05-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多