【问题标题】:Count number of occurrences of a pattern in a file (even on same line)计算文件中模式的出现次数(即使在同一行)
【发布时间】:2011-02-23 22:11:09
【问题描述】:

在文件中搜索某个字符串出现的次数时,我一般使用:

grep pattern file | wc -l

但是,由于 grep 的工作方式,这只会在每行中找到一次。如何搜索字符串在文件中出现的次数,无论它们是在同一行还是不同行?

另外,如果我正在搜索一个正则表达式模式,而不是一个简单的字符串,该怎么办?我如何计算这些,或者更好的是,在新行上打印每个匹配项?

【问题讨论】:

    标签: search count grep match


    【解决方案1】:

    要计算所有出现次数,请使用-o。试试这个:

    echo afoobarfoobar | grep -o foo | wc -l
    

    当然还有man grep (:

    更新

    有些人建议只使用grep -co foo 而不是grep -o foo | wc -l

    不要。

    此快捷方式并非在所有情况下都有效。手册页说:

    -c print a count of matching lines
    

    这些方法的区别如下所示:

    1.

    $ echo afoobarfoobar | grep -oc foo
    1
    

    只要在行中 (a{foo}barfoobar) 找到匹配项,搜索就会停止。仅检查了一行并匹配,因此输出为1。实际上-o在这里被忽略了,你可以使用grep -c来代替。

    2.

    $ echo afoobarfoobar | grep -o foo
    foo
    foo
    
    $ echo afoobarfoobar | grep -o foo | wc -l
    2
    

    在 (a{foo}bar{foo}bar) 行中找到了两个匹配项,因为我们明确要求查找每个出现 (-o)。每次出现都打印在单独的行上,wc -l 只计算输出中的行数。

    【讨论】:

    • 哇……真的这么简单吗?
    • grep -oc 在这种情况下不起作用。试试 echo afoobarfoobar | grep -oc foo
    • 有没有办法对多个文件执行此操作?假设我想查看一组文件中每个文件的出现次数。我可以使用 grep -c * 来每行,但不是每个实例。
    • grep -o foo a.txt b.txt | sort | uniq -c 工作得很好(使用 GNU grep):gist.github.com/hudolejev/81a05791f38cbacfd4de3ee3b44eb4f8
    【解决方案2】:

    试试这个:

    grep "string to search for" FileNameToSearch | cut -d ":" -f 4 | sort -n | uniq -c
    

    示例:

    grep "SMTP connect from unknown" maillog | cut -d ":" -f 4 | sort -n | uniq -c
      6  SMTP connect from unknown [188.190.118.90]
     54  SMTP connect from unknown [62.193.131.114]
      3  SMTP connect from unknown [91.222.51.253]
    

    【讨论】:

      【解决方案3】:

      迟来的帖子:
      使用搜索正则表达式模式作为 awk 中的记录分隔符 (RS)
      这允许您的正则表达式跨越\n-delimited 行(如果您需要它)。

      printf 'X \n moo X\n XX\n' | 
         awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'
      

      【讨论】:

        【解决方案4】:

        Ripgrep,它是 grep 的快速替代品,刚刚在 0.9 版本中引入了允许计数 each 匹配的 --count-matches 标志(我使用上面的示例保持一致):

        > echo afoobarfoobar | rg --count foo
        1
        > echo afoobarfoobar | rg --count-matches foo
        2
        

        根据 OP 的要求,ripgrep 也允许使用正则表达式模式 (--regexp &lt;PATTERN&gt;)。 它还可以在单​​独的行上打印每个(行)匹配:

        > echo -e "line1foo\nline2afoobarfoobar" | rg foo
        line1foo
        line2afoobarfoobar
        

        【讨论】:

          【解决方案5】:

          破解 grep 的颜色函数,并计算它打印出多少个颜色标签:

          echo -e "a\nb  b b\nc\ndef\nb e brb\nr" \
          | GREP_COLOR="033" grep --color=always  b \
          | perl -e 'undef $/; $_=<>; s/\n//g; s/\x1b\x5b\x30\x33\x33/\n/g; print $_' \
          | wc -l
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-05-14
            • 2014-04-22
            • 2021-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多