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

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

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


评论

我知道已指定grep,但对于使用ack的任何人,答案都只是ack -ch

@KyleStrand对我而言,ack -ch 仅计算出现次数的行,而不计算出现次数的行数

@MarcKees看手册页,听起来像是正确的行为。感谢您指出!!

#1 楼

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


评论


请注意,这需要GNU grep(Linux,Cygwin,FreeBSD,OSX)。

–吉尔斯'所以-不再是邪恶的'
2011年5月15日14:37



@wag \ b和\ B在这里做什么魔术?

–极客
14年6月12日在8:36

@Geek \ b匹配单词边界,\ B不匹配单词边界。如果在两端都使用\ b,则上面的答案会更正确。

–利亚姆
2015年9月25日在21:02



对于每行出现的次数,请结合使用grep -n选项和uniq -c ... grep -no'\ '文件| uniq -c

–Jameswarren
16-10-7在13:56



@jameswarren uniq仅删除相邻的相同行,如果您不确定重复项是否总是相邻,则需要先进行排序,然后再输入uniq。

–tripleee
16年11月3日,12:21

#2 楼

如果您有GNU grep(始终在Linux和Cygwin上,有时在其他地方),则可以计算grep -o的输出行:grep -o needle | wc -l。即使固定后也是如此。 。例如,如果您要查找整个单词,则首先将每个非单词字符都换行。

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'


否则,没有标准命令可以执行此操作特殊的文本处理,因此您需要转向sed(如果您是受虐狂)或awk。

# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'


这是使用sedgrep的更简单的解决方案,它适用于字符串或什至按书的正则表达式,但在少数带有锚定模式的极端情况下会失败(例如,它在^needle中发现了两次出现的\bneedleneedleneedle)。
请注意,在上述sed替换中,我使用\n表示换行符。这是模式部分的标准功能,但是在替换文本中,为了便于移植,请用\n代替反斜杠换行符。

#3 楼

如果像我一样,您实际上想要“两个;每个都正好一次”(实际上是“两个;都两次”),那么这很简单:

输出2

这种方法的好处(如果只需要一次)就是易于扩展。

评论


我不确定您是否真的要检查它只出现一次?您正在寻找的只是这些单词中的任何一个至少存在一次。

–史蒂夫·戈尔(Steve Gore)
18年7月11日在2:29

这应该是公认的答案。无需使用wc -l,grep具有一个内置选项来对事物进行计数,它甚至被命名为-c来表示“计数”!

–地毯
20年8月6日在20:03



#4 楼

另一种使用awk和needle作为字段分隔符的解决方案: >
awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'


或使用类:needle包含所有非字母字符。

评论


请注意,这需要一个支持regexp字段分隔符的awk(例如GNU awk)。

–吉尔斯'所以-不再是邪恶的'
2011年5月15日下午14:38

#5 楼

这是我的纯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


#6 楼

您的示例仅打印出每行出现的次数,而不显示文件中的总数。如果您想要的是这样的话,可能会起作用:

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


评论


没错-我的示例仅计算第一行中的出现次数。

–用户4518
2011年2月6日15:49