Shell 统计特定文件中的词频,计算机善于计数。我们经常要进行各种统计,例如发送垃圾邮件的站点数、不同页面的下载量或是文本中单词出现的频率。本章将展示如何统计文本中的单词词频。其中用到的技术也可以应用于日志文件、数据库输出等方面。
预备知识
我们可以使用awk
的关联数组来解决这个问题,而且实现方法还不止一种。单词是由空格或点号分隔的字母组合。首先,我们需要解析出给定文件中出现的所有单词,然后统计每个单词的出现次数。单词解析可以用正则表达式配合sed
、awk
或grep
等工具来完成。
实战演练
我们已经了解了实现原理。现在来动手创建如下的脚本:
#!/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
工作原理
egrep
命令将文本文件转换成单词流,每行一个单词。模式\b[[:alpha:]]+\b
能够匹配每个单词并去除空白字符和标点符号。选项-o
打印出匹配到的单词,一行一个。
awk
命令统计每个单词。它针对每一行文本执行{}
语句块中的语句,因此我们不需要再专门为此写一个循环。count[$0]++
命令负责计数,其中$0
是当前行,count
是关联数组。所有的行处理完毕后,END{}
语句块打印出各个单词及其数量。
整个处理过程也能够使用我们学过的其他工具来改写。可以利用tr
命令将大写单词和非大写单词合计为一个单词,然后用sort
命令排序输出:
egrep -o "\b[[:alpha:]]+\b" filename | tr [A-Z] [a-z] | \
awk '{ count[0]++ }
END{ printf("%-14s%s\n","Word","Count") ;
for(ind in count)
{ printf("%-14s%d\n",ind,count[ind]);
}
}' | sort
阅读本篇文章可以参考awk 命令 和 Bash中的数组 相关知识。