it-swarm.cn

使用grep计算出现的总数

grep -c对于查找字符串在文件中出现的次数很有用,但是每行仅对一次出现进行计数。如何计算每行多次出现?

我正在寻找比以下更优雅的东西:

Perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'
242
user4518

grep的-o仅输出匹配项,忽略行; wc可以计算它们:

grep -o 'needle' file | wc -l

这也将匹配“针”或“多针”。

要仅匹配单个单词,请使用以下命令之一:

grep -ow 'needle' file | wc -l
grep -o '\bneedle\b' file | wc -l
grep -o '\<needle\>' file | wc -l
352
wag

如果您有GNU grep(始终在Linux和Cygwin上,有时在其他地方)),则可以 计数grep -ogrep -o needle | wc -l

使用Perl,以下是我发现比您更优雅的几种方法(即使在 fixed 之后)。

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之前,将输入分成单个匹配项。例如,如果您要查找整个单词,则首先将每个非Word字符都换行。

# 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

这是使用sedgrep的更简单的解决方案,该解决方案适用于字符串,甚至是按书的正则表达式,但在某些锚定模式的极端情况下失败(例如,它发现了^needle的两次出现)或needleneedle中的\bneedle)。

sed 's/needle/\n&\n/g' | grep -cx 'needle'

请注意,在上面的sed替换中,我使用\n表示换行符。这是模式部分的标准配置,但是在替换文本中,为了便于携带,请用\n替换反斜杠换行符。

18

如果像我一样,你真的想要 “两个;每个正好一次”, (实际上是“两次;两次”),然后很简单:

grep -E "thing1|thing2" -c

并检查输出2

这种方法的好处(如果只想一次is您想要的是)可以轻松扩展。

5
OJFord

使用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}'

或使用课程:[^[:alnum:]]包含所有非字母字符。

3
ripat

这是我的纯bash解决方案

#!/bin/bash

B=$(for i in $(cat /tmp/a | sort -u); do
echo "$(grep $i /tmp/a | wc -l) $i"
done)

echo "$B" | sort --reverse
1
Felipe

您的示例仅打印出每行出现的次数,而不显示文件中的总数。如果这是您想要的,则可能会执行以下操作:

Perl -nle '$c+=scalar(()=m/needle/g);END{print $c}' 
1
jsbillings