【问题标题】:how do I use the grep --include option for multiple file types?如何对多种文件类型使用 grep --include 选项?
【发布时间】:2012-05-24 01:15:24
【问题描述】:

当我想 grep 某个目录中的所有 html 文件时,我会执行以下操作

grep --include="*.html" pattern -R /some/path

效果很好。问题是如何grep某个目录下的所有html,htm,php文件?

从这个Use grep --exclude/--include syntax to not grep through certain files看来,我可以做到以下几点

grep --include="*.{html,php,htm}" pattern -R /some/path

但遗憾的是,它对我不起作用。
仅供参考,我的 grep 版本是 2.5.1。

【问题讨论】:

    标签: shell grep


    【解决方案1】:

    您可以使用多个--include 标志。这对我有用:

    grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/
    

    但是,您可以使用 Deruijter suggested。这对我有用:

    grep -r --include=*.{html,php,htm} "pattern" /some/path/
    

    别忘了你也可以使用findxargs 来做这种事情:

    find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"
    

    【讨论】:

    • 我看到了问题。我使用了 --include=".{html,php}" 来防止 shell 扩展 '' 同时停止 shell 扩展 {html,php}。似乎 --include=* 中的等号能够防止shell扩展'*'。
    • xargs 并不是真正的替代品;很多时候,当您需要此功能时,您处理的文件比 xargs 处理的要多。
    • @JamesMoore:看看GNU Parallel。它通常可以用作xargs 的替代品。 This 也值得快速阅读。 HTH。
    • @tianyapiaozi:你说得对,大括号扩展周围的引用是问题所在;但是,如果没有引用,* 仍然会被通配作为它嵌入的令牌的一部分,它只是碰巧在这种情况下不匹配任何东西,因为只有 literally 命名为 --include=foo.html 的文件才会匹配。为了安全起见,请引用*(您可以单独使用\*)。作为一个额外的好处,这使得 视觉上 更清楚的是 不是在这种情况下应该执行 globbing 的 shell
    • 至于find 解决方案:使用-exec grep "pattern" {} + 而不是| xargs grep "pattern" 更健壮(例如处理带空格的文件名)以及更高效。
    【解决方案2】:

    使用 {html,php,htm} 只能用作 brace expansion,这是 bashkshzsh 的非标准(不符合 POSIX)功能。 p>

    • 换句话说:不要尝试在以/bin/sh 为目标的脚本中使用它 - 在这种情况下使用显式 多个--include 参数。

    • grep 本身理解{...} 表示法。

    要识别大括号扩展,它必须是命令行上的未引用(a 的一部分)标记

    大括号扩展扩展到多个参数,所以在手头的情况下 grep 最终会看到 multiple @987654331 @options,就像你单独传递它们一样。

    大括号扩展的结果会受到通配(文件名扩展)的影响,这有陷阱

    • 如果每个结果参数恰好包含 未引用 通配元字符(例如 *),则可以将其进一步扩展为匹配的文件名。
      虽然这对于诸如--include=*.html 之类的标记不太可能(例如,您必须有一个文件字面上命名 类似--include=foo.html 的东西才能匹配),但总的来说值得牢记.

    • 如果nullglob shell 选项恰好打开 (shopt -s nullglob) 并且通配符匹配nothing,则该参数将被丢弃

    因此,对于完全稳健的解决方案,请使用以下内容:

    grep -R '--include=*.'{html,php,htm} pattern /some/path
    
    • '--include=*.' 被视为文字,因为被单引号;这可以防止无意中将* 解释为通配符。

    • {html,php,htm},必要的 - 未引用大括号扩展[1] , 扩展为 3 个参数,由于{...} 直接跟在'...' 标记之后,包括该标记。

    • 因此,在 shell 移除引号后,以下 3 literal 参数最终会传递给 grep

      • --include=*.html
      • --include=*.php
      • --include=*.htm

    [1] 更准确地说,只有大括号扩展的 syntax-relevant 部分必须不加引号,列表元素 仍然可以单独引用如果它们包含可能导致大括号扩展后不需要的通配符的通配元字符,则必须是;虽然在这种情况下没有必要,但上面的内容可以写成
    '--include=*.'{'html','php','htm'}

    【讨论】:

    • 非常感谢您的这篇文章。伟大的帖子不仅回答了这个问题,而且教你一些新的东西!这对于我们这些写需要符合 POSIX 的东西的人来说特别有用。任何使用 Mac OS X 的人都应该看这里!
    • @sabalaba:我很高兴听到这个消息,但要明确一点:虽然大括号扩展不符合 POSIX 标准,但它可以在 bash 运行的任何平台上与 bash 一起使用。
    【解决方案3】:

    试着去掉双引号

    grep --include=*.{html,php,htm} pattern -R /some/path
    

    【讨论】:

    • @tianyapiaozi 试试grep --include=\*.{html,php,htm} pattern -R /some/path。它对我有用。
    【解决方案4】:

    这不工作吗?

      grep pattern  /some/path/*.{html,php,htm} 
    

    【讨论】:

    • 并非如此。这些文件可以驻留在子目录的子目录中
    【解决方案5】:

    它的工作原理相同,但没有--include 选项。它也适用于 grep 2.5.1。

    grep -v -E ".*\.(html|htm|php)"
    

    【讨论】:

      【解决方案6】:

      试试这个。 -r 将进行递归搜索。 -s 将抑制文件未找到错误。 -n 将显示找到该模式的文件的行号。

          grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}
      

      【讨论】:

      • 这对我来说尤其是最好的答案,我认为您可以使用 -rsn 而不是 -r -s -n (但这是挑剔的)。
      • 我通常使用 -rns。为了在示例中清晰起见,我不得不提到 -r -n -s :-) 很高兴它有帮助。
      • 我建议将-I 添加到标准集。它跳过二进制文件(几乎从未搜索过),因此提高了效率。然后我们去grep -rIns ...,它的声音很好听:)
      • 这会搜索每个文件,而不仅仅是匹配表达式正则表达式的文件。当您知道扩展名或通过名称识别文件的其他方式时,它是准确的,但效率不高。
      【解决方案7】:

      grepfind 命令一起使用

      find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
       -exec grep PATTERN {} \+
      

      您也可以使用-regex-regextype 选项。

      【讨论】:

        猜你喜欢
        • 2021-04-01
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-21
        • 1970-01-01
        相关资源
        最近更新 更多