如何计算整个文件中字符串出现的次数?

4

有没有内置命令可以做到这一点,或者有没有任何脚本可以实现这一功能?

我想要计算一个特定字符串(而不是单词)在文件中出现的次数。这可以包括每行多个出现,因此计数应该计算每个出现次数,而不是只为具有2次或更多次字符串的行计数1次。

例如,对于这个样本文件:

blah(*)wasp( *)jkdjs(*)kdfks(l*)ffks(dl
flksj(*)gjkd(*
)jfhk(*)fj (*) ks)(*gfjk(*)

如果我想要统计字符串(*)出现的次数,我会期望计数为6,即第一行有2个,第二行有1个,第三行有3个。请注意,第2-3行之间由换行符隔开,因此不应该计算为一个出现次数。 更新: 迄今为止回答得非常好!我能否请求脚本处理(*)转换为\(*\)等的转换呢?这样我就可以只传递任何所需的字符串作为输入参数,而不用担心需要对其进行哪些转换以使其显示在正确的格式中。

我不太明白你的“更新”。你是在寻找Perl的quotemeta函数,还是在正则表达式中使用\Q\E - DavidO
@DavidO - 我不确定 quotemeta 是否能解决问题。基本上,我设想:var_input = "(*)"; var_proper_format = some_func(var_input); while /var_proper_format/g; ....即 var_proper_format 是从给定的输入 var_input 自动计算出来的。 - toop
6个回答

23

你可以使用基本工具,例如grepwc

grep -o '(\*)' input.txt | wc -l

这个如何编写成一个接受参数的脚本? - toop
在编程中,可以使用以下代码:+1 或者一个可验证的 echo $'blah(*)wasp( *)jkdjs(*)kdfks(l*)ffks(dl\nflksj(*)gjkd(*\n)jfhk(*)fj (*) ks)(*gfjk(*)' | grep -o '(\*)' | wc -l - l0b0

6

使用perl的“Eskimo kiss”运算符和-n开关,在结尾处打印总数。使用\Q...\E忽略任何元字符。

perl -lnwe '$a+=()=/\Q(*)/g; }{ print $a;' file.txt

脚本:

use strict;
use warnings;

my $count;
my $text = shift;

while (<>) {
    $count += () = /\Q$text/g;
}

print "$count\n";

使用方法:

perl script.pl "(*)" file.txt 

如何将此转换为接受参数的脚本? - toop
我不得不用这个工具处理一个没有换行符的多GB XML文件。grep+wc效果不太好,但是这个解决方案运行速度非常快,而且效果很棒!Go Perl! - Excalibur

2
这段代码循环遍历文件的每一行,在每一行中查找字符串“(*)”的所有出现次数。每次发现该字符串时,$c就会增加1。当没有更多行可遍历时,将打印$c的值。
更新:关于您的评论要求将其转换为接受正则表达式作为参数的解决方案,可以像这样实现:
这应该能解决问题。如果我感觉倾向于再次浏览perlrun,我可能会看到更优雅的解决方案,但是这应该可以工作。
您还可以通过为正则表达式提供列表上下文来消除显式内部while循环,以使用隐式循环:
这段代码的意思是在filename.txt文件中查找regex字符串,并统计它出现的次数。

这个如何编写成一个接受参数的脚本? - toop
@toop 请看我的更新,提供了一种允许您在命令行上指定正则表达式的解决方案。 - DavidO

1
您可以使用基本的grep命令: 示例: 如果您想在文件中查找“hello”单词出现的次数。
grep -c "hello" filename

如果您想查找模式出现的次数,则需要:
grep -c -P "Your Pattern"

模式示例:hell.w,\d+等。

0
我使用了以下命令在文件中查找特定字符串的数量:
grep search_String fileName|wc -l

1
这个问题要求使用Perl解决方案,而Arjit的答案已经给出了使用grep -c解决此问题的“完美”方式。从这个意义上说:你的答案在这里并没有真正添加任何有用的东西。 - GhostCat

-1
text="(\*)"
grep -o $text file | wc -l

你可以将它制作成一个接受参数的脚本,就像这样:

脚本计数

#!/bin/bash
text="$1"
file="$2"
grep -o "$text" "$file" | wc -l

使用方法:

./count "(\*)" file_path

这与得票最多的答案相同。您是否试图重新发布所有bash答案? - Michele d'Amico
有人想把这个变成一个脚本,我正在处理。 - Jahid
评论或编辑答案时,请添加您的贡献...提交新答案只是噪音。 - Michele d'Amico
1
编辑别人的答案并添加自己的不太公平。而且注释代码也不是很高效。 - Jahid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接