【发布时间】:2015-07-02 21:28:38
【问题描述】:
给定一个包含文本的文件,我想计算字符串“ABCDXYZ”的出现次数?
$ cat file.txt
foo
bar
foo
bar
baz
baz
bug
bat
foo
bar
so
on
and
so
on
foo
让我们数数foo!
【问题讨论】:
-
编辑您的问题以包含字符串
foobar并提供预期的输出。
给定一个包含文本的文件,我想计算字符串“ABCDXYZ”的出现次数?
$ cat file.txt
foo
bar
foo
bar
baz
baz
bug
bat
foo
bar
so
on
and
so
on
foo
让我们数数foo!
【问题讨论】:
foobar 并提供预期的输出。
很多时候我看到人们使用以下来计算单词:
$ grep -o 'foo' file.txt | wc -l
这里有几个例子:1、2、3 甚至是this youtube video。
这确实是一个糟糕的方式,原因如下:
man grep 或 BSD grep (NetBSD, OpenBSD, FreeBSD) 或 GNU grep
-c 的选项。
NetBSD 手册页非常清楚地描述了这些选项:-c, --count Suppress normal output; instead print a count of matching lines for each input file. With the -v, --invert-match option (see below), count non-matching lines.
您只能使用一个命令:
$ grep foo -c file.txt
不仅可以,而且应该阅读手册页并了解手头的工具,从而节省大量搜索时间!
速度加成
您还可以让您的greps 更快,因为管道非常昂贵。
与使用选项 -c 相比,管道上方显示的短文件之一慢 2 倍:
$ time grep foo -c file.txt
4
real 0m0.001s
user 0m0.000s
sys 0m0.001s
$ time grep -o 'foo' file.txt | wc -l
4
real 0m0.002s
user 0m0.000s
sys 0m0.003s
对于大文件,这可能更为重要。在这里我将我的文件复制到更大的时间十万次:
$ for i in `seq 1 300000`; do cat file.txt >> largefile.txt; done
^C
$ wc -l largefile.txt
1111744 largefile.txt
现在这里是使用管道的速度:
$ time grep -o foo largefile.txt | wc -l
277936
real 0m0.216s
user 0m0.214s
sys 0m0.010s
这是仅使用 grep 的速度:
$ time grep -c foo largefile.txt
277936
real 0m0.032s
user 0m0.028s
sys 0m0.004s
这些基准测试是在具有 Core i5 和大量 RAM 的机器上完成的,它在 RAM 和 CPU 资源很少的嵌入式设备上会非常重要。
总之,不要在不需要的地方使用管道。 UNIX 工具通常具有重叠的功能。了解您的工具,了解如何使用它们!
要计算一个单词在文件中出现的次数,使用它就足够了:
$ grep -c <word> <filename>
【讨论】:
foobar 的出现次数,就好像它找到了单词foo。这是可取的吗?您在寻找单词或字符串吗?您的问题可以互换使用这些术语,但它们非常不同,并且您使用的 grep 命令不搜索它们,它搜索正则表达式,因此您想查找文件中存在的字符串 f.o 和 foo 然后 @ 987654346@ 将不受欢迎。有关如何搜索单词和字符串的详细信息,请参见 grep 手册页。
如果您想泛化以计算所有个单词,请使用:
sort file.txt | uniq -c
【讨论】: