在搜索文件中字符串的出现次数时,我通常使用:
grep pattern file | wc -l
但是,由于 grep 的工作方式,这只会在每行中找到一次。如何搜索字符串在文件中出现的次数,无论它们是在同一行还是不同行?
另外,如果我正在搜索正则表达式模式,而不是简单的字符串,该怎么办?我如何计算这些,或者更好的是,在新行上打印每个匹配项?
要计算所有出现次数,请使用-o
. 尝试这个:
echo afoobarfoobar | grep -o foo | wc -l
当然man grep
(:
有些人建议使用 justgrep -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 "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]
迟来的帖子:
使用搜索正则表达式模式作为记录分隔符 (RS),awk
这允许您的正则表达式跨越\n
-delimited 行(如果需要)。
printf 'X \n moo X\n XX\n' |
awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'
Ripgrep是 grep 的快速替代品,它刚刚在 0.9 版本中引入了--count-matches
允许计算每个匹配项的标志(我使用上面的示例来保持一致):
> echo afoobarfoobar | rg --count foo
1
> echo afoobarfoobar | rg --count-matches foo
2
正如 OP 所要求的,ripgrep 也允许使用正则表达式模式(--regexp <PATTERN>
)。它还可以在单独的行上打印每个(行)匹配:
> echo -e "line1foo\nline2afoobarfoobar" | rg foo
line1foo
line2afoobarfoobar
破解 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