grep -c
对于查找某个字符串在文件中出现的次数很有用,但它只对每行的每次出现进行一次计数。如何计算每行多次出现的次数?
我正在寻找比以下更优雅的东西:
perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'
答案1
grep-o
只会输出匹配项,忽略行;wc
可以数一下:
grep -o 'needle' file | wc -l
这也将匹配“needles”或“multineedle”。
要仅匹配单个单词,请使用以下命令之一:
grep -ow 'needle' file | wc -l
grep -o '\bneedle\b' file | wc -l
grep -o '\<needle\>' file | wc -l
答案2
如果您有 GNU grep(总是在 Linux 和 Cygwin 上,偶尔在其他地方),您可以计算输出行数grep -o
: grep -o needle | wc -l
。
对于 Perl,我发现以下几种方法比你的更优雅(即使它是固定的)。
perl -lne 'END {print $c} map ++$c, /needle/g'
perl -lne 'END {print $c} $c += s/needle//g'
perl -lne 'END {print $c} ++$c while /needle/g'
仅使用 POSIX 工具时,一种方法(如果可能)是将输入拆分为具有单个匹配项的行,然后再将其传递给 grep。例如,如果您要查找整个单词,请首先将每个非单词字符转换为换行符。
# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'
否则,没有标准命令来执行此特定的文本处理,因此您需要转向 sed(如果您是受虐狂)或 awk。
awk '{while (match($0, /set/)) {++c; $0=substr($0, RSTART+RLENGTH)}}
END {print c}'
sed -n -e 's/set/\n&\n/g' -e 's/^/\n/' -e 's/$/\n/' \
-e 's/\n[^\n]*\n/\n/g' -e 's/^\n//' -e 's/\n$//' \
-e '/./p' | wc -l
这是一个使用sed
and 的更简单的解决方案grep
,它适用于字符串甚至常规正则表达式,但在一些带有锚定模式的极端情况下会失败(例如,它在 中找到两次出现的^needle
or )。\bneedle
needleneedle
sed 's/needle/\n&\n/g' | grep -cx 'needle'
请注意,在上面的 sed 替换中,我\n
指的是换行符。这在模式部分是标准的,但在替换文本中,为了可移植性,用反斜杠换行符替换\n
。
答案3
如果像我一样,您实际上想要“两者;每个恰好一次”,(这实际上是“任一;两次”)那么它很简单:
grep -E "thing1|thing2" -c
并检查输出2
。
这种方法的好处(如果恰好一次是你想要的)是它很容易扩展。
答案4
我需要这样做,但对于多个搜索词。我希望将它们列在列中,并列出每个列的出现次数。
我的仅 bash、一行的解决方案如下:
grep -o -E 'borp|flarb' flarb.log | sort | uniq -c
910 borp
9090 flarb