我想在文本文件中查找 10 个最常见的单词。首先,解决方案应该针对击键进行优化(换句话说 - 我的时间)。其次,为了表演。以下是我迄今为止获得前 10 名的内容:
cat test.txt | tr -c '[:alnum:]' '[\n*]' | uniq -c | sort -nr | head -10
6 k
2 g
2 e
2 a
1 r
1 k22
1 k
1 f
1 eeeeeeeeeeeeeeeeeeeee
1 d
我可以制作一个 java、python 等程序,将(单词、numberOfOccurences)存储在字典中并对值进行排序,或者我可以使用 MapReduce,但我会针对击键进行优化。
是否存在误报?有没有更好的办法?
答案1
这几乎是查找“N 个最常见的事物”的最常见方法,除了您缺少 a sort
,并且您有一个免费的cat
:
tr -c '[:alnum:]' '[\n*]' < test.txt | sort | uniq -ci | sort -nr | head -10
sort
如果你不在 the之前添加 a ,uniq -ci
你可能会得到很多错误的单例单词。 uniq
只有独特的线条,而不是整体的独特性。
您可能想使用一个技巧,“停止词”。如果您正在查看英语文本(抱歉,这里是单语北美语),像“of”、“and”、“the”这样的词几乎总是占据前两到三个位置。您可能想消除它们。 GNU Groff 发行版有一个名为eign
其中的文件,其中包含相当不错的停用词列表。我的 Arch 发行版有/usr/share/groff/current/eign
,但我想我也见过/usr/share/dict/eign
或/usr/dict/eign
在旧的 Unix 中。
您可以像这样使用停用词:
tr -c '[:alnum:]' '[\n*]' < test.txt |
fgrep -v -w -f -i /usr/share/groff/current/eign |
sort | uniq -ci | sort -nr | head -10
我的猜测是,大多数人类语言需要从有意义的词频计数中删除类似的“停用词”,但我不知道在哪里建议获取其他语言的停用词列表。
-w
on 标志启用fgrep
全字匹配。这可以避免仅包含短暂停止词的单词(例如“a”或“i”)出现误报。该-i
标志打开uniq
并fgrep
在比较单词时忽略大小写。
答案2
这对于 utf-8 效果更好:
$ sed -e 's/\s/\n/g' < test.txt | sort | uniq -c | sort -nr | head -10
答案3
让我们使用 AWK 吧!
此函数按降序列出提供的文件中每个单词出现的频率:
function wordfrequency() {
awk '
BEGIN { FS="[^a-zA-Z]+" } {
for (i=1; i<=NF; i++) {
word = tolower($i)
words[word]++
}
}
END {
for (w in words)
printf("%3d %s\n", words[w], w)
} ' | sort -rn
}
您可以在文件中这样调用它:
$ cat your_file.txt | wordfrequency
对于前 10 个单词:
$ cat your_file.txt | wordfrequency | head -10
来源:AWK 病态 Ruby
答案4
让我们使用哈斯克尔吧!
这正在变成一场语言战争,不是吗?
import Data.List
import Data.Ord
main = interact $ (=<<) (\x -> show (length x) ++ " - " ++ head x ++ "\n")
. sortBy (flip $ comparing length)
. group . sort
. words
用法:
cat input | wordfreq
或者:
cat input | wordfreq | head -10