我有一个像这样的文本文件:
tom
and
jerry
went
to
america
and
england
我想知道每个单词出现的频率。
当我尝试以下命令时
cat test.txt |sort|uniq -c
我得到以下输出
1 america
2 and
1 england
1 jerry
1 to
1 tom
1 went
但我也需要部分匹配。即to
单词 中出现的单词tom
。所以我的预期字数to
是 2。可以使用unix
命令吗?
答案1
这是一种方法,但不是很优雅:
$ sort -u file | while IFS= read -r word; do
printf '%s\t%s\n' "$word" "$(grep -cFe "$word" file)";
done
america 1
and 3
england 1
jerry 1
to 2
tom 1
went 1
答案2
一种awk
方法:
awk '
!x {c[$0]; next}
{for (i in c) if (index($0, i)) c[i]++}
END{for (i in c) print c[i]"\t"i}' file x=1 file | sort -k1rn
您的输入给出了哪些
3 and
2 to
1 america
1 england
1 jerry
1 tom
1 went
我们分两遍处理输入。在第一遍中,我们将不同单词的列表记录为c
哈希表的键。
在第二遍中,对于文件中的每一行,我们循环遍历所有键,c
如果在该行中找到该键,则增加相应的值。
文件中不同单词的列表最终存储在内存中。如果这些是英语单词,那应该不成问题,因为英语中的不同单词只有不到 200,000 个。
答案3
这不会使系统崩溃,但可能需要很长时间才能运行,因为它会多次解析输入。假设输入文件名为“in”:
sort -u < in | while read w
do
printf "%d\t%s\n" `grep -c "$w" in` "$w"
done
你的输入让我:
1 america
3 and
1 england
1 jerry
2 to
1 tom
1 went
答案4
我不清楚部分匹配是否要锚定到行的开头。假设答案是肯定的,那么什么可能这里加快速度的是通过古老的命令使用二分搜索look
。当然look
需要对其输入文件进行排序。因此,首先创建原始文件的排序版本
sort file > file.sorted
然后循环遍历原始文件,look
一次根据排序后的文件查找一个单词。
while read -r word; do
printf "%s %d\n" "$word" "$(look -b "$word" file.sorted | wc -l)";
done <file
有些系统不需要-b
传递标志来look
强制进行二分搜索。排序文件的磁盘缓存可以帮助进一步加快速度