如何从非常大的文件中获取单词的唯一出现?

如何从非常大的文件中获取单词的唯一出现?

我被要求使用 unix/ shell 脚本编写一个词频分析程序,具有以下要求:

  • 输入是一个文本文件,每行一个单词
  • 输入单词取自《紧凑型牛津英语词典新版》
  • 字符编码为UTF-8
  • 输入文件的长度为 1 Pebibyte (PiB)
  • 输出的格式为“单词出现N次”

我知道一种开始方法如下 --- cat filename | xargs -n1 | xargs -n1 |排序| uniq -c > 新文件名

考虑到性能,最好的最佳方法应该是什么?

答案1

注意:

这是一款付费产品,尽管是开源的,因此您可以免费自行安装和运行它。不过,如果您愿意,您可以免费试用,在我们的云中进行测试。我不一定希望您购买帐户,但如果您需要处理非常大的文本文件中的数据,Manta 就能完美地做到这一点。

此外,我在 Joyent 工作,该公司销售该产品,因此对我的意见持保留态度,但我鼓励您亲自尝试该产品并让它证明自己。

乔伊恩特的对象存储蝠鲼非常适合处理大量数据输入并在我们的系统上针对它们运行计算。

Manta 的用途是广阔的但我会特别关注你的问题:

对数据运行计算

上传一些数据集:

$ curl -sL http://www.gutenberg.org/ebooks/1661.txt.utf-8 | \
    mput -H 'content-type: text/plain' ~~/stor/books/sherlock_holmes.txt
$ curl -sL http://www.gutenberg.org/ebooks/76.txt.utf-8 | \
    mput -H 'content-type: text/plain' ~~/stor/books/huck_finn.txt
$ curl -sL http://www.gutenberg.org/ebooks/2701.txt.utf-8 | \
    mput -H 'content-type: text/plain' ~~/stor/books/moby_dick.txt
$ curl -sL http://www.gutenberg.org/ebooks/345.txt.utf-8 | \
    mput -H 'content-type: text/plain' ~~/stor/books/dracula.txt

对您的数据运行作业

下面是一个示例作业,用于计算“吸血鬼”一词在《德古拉》中出现的次数。

$ echo ~~/stor/books/dracula.txt | mjob create -o -m "grep -ci vampire"
added 1 input to 7b39e12b-bb87-42a7-8c5f-deb9727fc362
32

此命令创建一个作业以在每个输入对象上运行用户脚本grep -ci vampire,然后~~/stor/books/dracula.txt作为作业的唯一输入提交。作业的名称是(在本例中)7b39e12b-bb87-42a7-8c5f-deb9727fc362。作业完成后,结果将放置在输出对象中,您可以使用以下mjob outputs命令查看该对象


您可以使用类似的调用在下面的所有对象上运行相同的作业 ~~/stor/books:

$ mfind -t o ~~/stor/books | mjob create -o -m "grep -ci human"
added 5 inputs to 69219541-fdab-441f-97f3-3317ef2c48c0
13
48
18
4
6

在此示例中,系统运行 5 次调用grep。其中每一个都称为一个任务。每项任务都会产生一个输出,而作业本身最终会产生 5 个独立的输出。


映射和减少阶段

我们刚刚描述了传统映射归约计算的“映射”阶段。 “映射”阶段对每个输入对象执行相同的计算。缩减阶段通常组合来自映射阶段的输出以产生单个输出。


早期的一个例子计算了“人类”一词在每本书中出现的次数。我们可以awk在reduce阶段使用一个简单的脚本来获取“人类”在所有书籍中出现的总次数。

$ mfind -t o ~~/stor/books | \
        mjob create -o -m "grep -ci human" -r "awk '{s+=\$1} END{print s}'"
added 5 inputs to 12edb303-e481-4a39-b1c0-97d893ce0927
89

该作业有两个阶段:映射阶段grep -ci human在每个输入对象上运行,然后缩减阶段awk在第一阶段的串联输出上运行脚本。awk '{s+=$1} END {print s}'对数字列表求和,因此它对第一阶段得出的数字列表求和。您可以组合多个映射和减少阶段。任何非最终阶段的输出都将成为下一阶段的输入,而最终阶段的输出将成为作业输出。


我不太确定您到底在寻找什么,但这更接近您问题中的命令:

echo ~~/stor/books/dracula.txt | mjob create -o -m "cat" -r "tr -s '[:blank:]' '[\n*]'" -r "sort" -r "uniq -c" >./tmp/test.txt

输出

   2559
      1 "'Are
      1 "'E's
      1 "'I
      1 "'Ittin'
      1 "'Little
      1 "'Lucy,
      1 "'Maybe
      1 "'Miss
      2 "'My
      1 "'Never
      1 "'No'
      1 "'Ow
      1 "'Silence!
      1 "'That's
      1 "'Tyke
      1 "'Wilhelmina'--I
      1 "'Yes,
      8 "A
      ...

相关内容