Answers:
grep -o
只会输出匹配项,而忽略行;wc
可以算一下:
grep -o 'needle' file | wc -l
这也将匹配“针”或“多针”。
只有一个字:
grep -o '\bneedle\B' file | wc -l
# or:
grep -o '\<needle\>' file | wc -l
\b
和\B
这里做?
uniq
仅删除相邻的相同行,如果您不确定重复项将始终紧邻sort
,uniq
则需要在输入之前删除。
如果您有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
和grep
,这适用于字符串或者甚至这书正则表达式,但在少数极端案例与锚定模式失败(如发现两次出现^needle
或\bneedle
在needleneedle
)。
sed 's/needle/\n&\n/g' | grep -cx 'needle'
请注意,在上面的sed替换中,我曾经\n
表示换行符。这是模式部分的标准功能,但是在替换文本中,为了便于移植,请使用反斜杠换行符\n
。
使用awk和needle
作为字段分隔符的另一种解决方案:
awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'
如果要匹配needle
后跟标点符号,请相应地更改字段分隔符,即
awk -F'^needle[ ,.?]|[ ,.?]needle[ ,.?]|[ ,.?]needle$' '{c+=NF-1}END{print c}'
或使用class:[^[:alnum:]]
包含所有非字母字符。
您的示例仅打印出每行出现的次数,而不显示文件中的总数。如果这就是您想要的,则可能会执行以下操作:
perl -nle '$c+=scalar(()=m/needle/g);END{print $c}'
grep
已经指定了,但是对于任何使用的人ack
,答案都是ack -ch <pattern>
。