问题
写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。
为了简单起见,你可以假设:
words.txt只包括小写字母和 ’ ’ 。
每个单词只由小写字母组成。
单词间由一个或多个空格字符分隔。
示例
words.txt
the day is sunny the the
the sunny is is
输出
the 4
is 3
sunny 2
day 1
答案
示范一
脚本
#!/bin/bash
end=$1
cat $2|
tr -cs "[a-z][A-Z]" "\n" |
tr A-Z a-z |
sort |
uniq -c |
sort -k1nr -k2 |
head -n$end
说明:
这段bash脚本接收两个参数,分别是 $1
和$2
,$1
表示显示频率最高的$1
个单词(即结果中的前$1
行),而$2
则表示要分析的文件路径。
接下来就是一系列命令了,这些命令用 | 符号分割开,该符号表示重定向,把上一个命令的结果传递给下一个命令。
cat 命令打开文件
tr 命令:tr是transform的缩写,该命令是著名的流处理命令sed的简化版,也是用来对文档进行转换的。
tr -cs “[a-z][A-Z]" “\n” -c表示取“[a-z][A-Z]"的补集(complement),-s 表示把连续的匹配压缩成一个”\n“,所以整个命令就是把除了字母外的其他字符一律压缩成换行符,如果有连续的匹配,则只转换成一个换行符。
tr A-Z a-z 把大写统一转换成小写。
sort 排序 按字母顺序
uniq 去重 该命令必须对排序好的文档进行,-c 表示打印出字母的重复次数
然后再次 sort ,这次sort比较复杂,因为在uniq命令后 输出结果已经变成了 如下形式:
n word (单词的重复次数+空格+单词)
所以 -k1nr表示对第一列(-k1)的数字形式(-n)的变量进行逆序(-r 从大到小)排列 , -k2表示在前面的排序基础上对重复次数一致的单词进行按字母顺序的排列。
最后是head -n$1
,表示只显示结果的前$1
行。
如果要显示第5行到第10行,则可以使用sed 命令 把head -n$1
替换成
sed -n '5,10p‘
示范二
tr -s "\t| " “\n” < filename | sort | uniq -c | sort -n -k 1 -r
参考:
https://blog.csdn.net/rav009/article/details/9964129
https://blog.csdn.net/xunmengpiaoyun/article/details/27355281