4.5 统计特定文件中的词频
查找文件中使用单词的频率是一个很有意思的练习,在这个练习中会应用到你已学到的文本处理技巧。统计词频的方法有很多种。让我们看看具体的做法。
4.5.1 预备知识
我们可以使用关联数组、awk
、sed
、grep
等不同的方式来解决这个问题。
4.5.2 实战演练
单词是由空格和点号分隔的字母组合。首先我们应该解析出给定文件中出现的所有单词,这样才能开始统计每个单词的个数。单词解析可以用正则表达式配合sed
、awk
或grep
等工具来完成。
要找出每个单词出现的次数,我们要采用一种与众不同的方法。有一种统计词频的方法是用一个循环来遍历每一个单词,然后用另一个循环来检查单词是否相同。如果相同,则增加计数并在文件尾部进行打印。这不是一种高效的方法。在关联数组中,我们将单词作为数组索引,单词计数作为数组值。通过遍历每一个单词,我们只需要使用一个循环就能完成统计任务。将数组值初始化为0,并使用array[word]=array[word] + 1
就可以得到一个包含各单词出现次数的数组。
现在就来动手试试吧。创建脚本如下:
#!/bin/bash
#文件名: word_freq.sh
#用途: 计算文件中单词的词频
if [ $# -ne 1 ];
then
echo "Usage: $0 filename";
exit -1
fi
filename=$1
egrep -o "\b[[:alpha:]]+\b" $filename | \
awk '{ count[$0]++ }
END{ printf("%-14s%s\n","Word","Count") ;
for(ind in count)
{ printf("%-14s%d\n",ind,count[ind]); }
}'
输出如下:
- $ ./word_freq.sh words.txt
- Word Count
- used 1
- this 2
- counting 1
4.5.3 工作原理
egrep -o "\b[[:alpha:]]+\b" $filename
用来只输出单词。用 -o
选项打印由换行符分隔的匹配字符序列。这样我们就可以在每行中列出一个单词。
\b
是单词边界标记符。[:alpha:]
是表示字母的字符类。
awk
命令用来避免对每一个单词进行迭代。因为awk
默认对每一行都执行{}
块中的语句,所以我们就不需要再为同样的事手动指定循环了。借助关联数组,当执行count[$0]++
时,单词计数就增加。最后,在END{}
语句块中通过迭代所有的单词,就可以打印出单词及它们各自出现的次数。
4.5.4 参考
1.6节讲解了Bash中的数组。
4.7节介绍了
awk
命令。