我有一些作业:
找出文件 alice 中有多少个唯一单词及其计数?将排序后的唯一单词打印到名为 alice_unique 的文件中。请注意,当您用撇号分割单词时,它们会正确分割,与任何其他特殊字符相同。
到目前为止我有这个
tr -sc 'A-Za-z' '\012' < alice | sort | uniq -c > alice_unique
但我不知道如何将带有特殊字符(',!,?等)的单词放在一起。或者如何计算唯一单词的总数。
文本文件爱丽丝(开头)
爱丽丝梦游仙境
刘易斯·卡罗尔
千年支点3.0版
第一章 掉进兔子洞
爱丽丝开始厌倦了坐在岸边姐姐身边,无所事事:有一两次她偷看了姐姐正在读的书,但里面没有图片或对话,“还有什么?”爱丽丝想,“这就是一本书的用途,没有图片或对话吗?”
所以她在心里思考(尽她所能,因为炎热的天气让她感到非常困倦和愚蠢),制作菊花链的乐趣是否值得费力起床采摘雏菊,突然,一只粉红色眼睛的白兔从她身边跑过来。
答案1
<alice tr -cd "[:alpha:][:space:]-'" |
tr ' [:upper:]' '\n[:lower:]' |
tr -s '\n' |
sed "s/^['-]*//;s/['-]$//" |
sort |
uniq -c > alice_unique
逐行:
- 删除除字母、空格、撇号和连字符之外的所有内容
- 将空格转换为换行符并将大写转换为小写
- “挤压”连续换行符
- 去掉前导或尾随撇号和连字符
- 对单词进行排序
- 显示每个唯一单词及其出现次数
如果你应该把数字算作单词,这是错误的。如果文本不是 ASCII,这可能不起作用。为了爱丽丝漫游仙境这可能已经足够好了。
答案2
试试这个,文本文件在哪里:
awk -- '{for (i = 1; i <= NF; i++) wc[$i] += 1}; END {for (w in wc) print w, wc[w]}' <file> | sort
默认情况下,awk 按空格分割每一行输入,生成字段 $1、$2、...,直至 NF,它提供输入字段数量的计数。它还隐式地迭代所有输入行。 END 标记给出了在处理完所有行后要执行的代码块。变量没有声明,方括号用于引用关联数组。
该 awk 程序获取每行的每个单词,使用该单词作为 wc[] 的索引,并添加到计数(如果尚未定义,则将其视为零)。因此,for 循环和所有行上的隐式外部循环都会对所有唯一单词进行计数(标点符号将导致它被计为不同的单词,但如果需要,这很容易修复)。然后 END 块打印出所有单词及其计数。
我使用管道进行排序以按顺序排列单词,而不是使 awk 程序复杂化。我还删除了之前的“-u”,因为每一行都是唯一的。
答案3
以下是AWK的解决方案。请注意,这是一个基本解决方案,可能需要扩展。例如,如果我们解析圣经,我们需要从单词中排除经文。
{
if (NR == 1) {
sub(/^\xef\xbb\xbf/,"")
}
gsub(/[,;!()*:?.]*/, "")
for (i = 1; i <= NF; i++) {
w = $i
words[w]++
}
}
END {
print length(words)
}
该程序会删除 BOM 字符,如果不这样做,就会使一个单词“唯一”。它去掉了一些基本的标点符号。在 for 循环中,我们对所有字段进行计数。
最后,我们得到了数组的长度。