拆分文件,将每个部分作为参数传递给脚本,并行运行每个脚本

ber*_*436 6 scripting bash split parallelism gnu-parallel

我有一个包含 10000 个单词(一行)的 words.txt。我有 5,000 个文件。我想查看哪些文档包含哪些单词(单词周围带有正则表达式)。我有一个脚本.sh,它可以搜索文档并输出命中。我想 (1) 将我的输入文件拆分为更小的文件 (2) 将每个文件作为参数提供给 script.sh 并且 (3) 并行运行所有这些。

我基于教程的尝试遇到了错误

$parallel ./script.sh ::: split words.txt # ./script.sh: line 22: split: No such file or directory
Run Code Online (Sandbox Code Playgroud)

我的 script.sh 看起来像这样

#!/usr/bin/env bash

line 1 while read line
line 2  do
        some stuff
line 22 done < $1
Run Code Online (Sandbox Code Playgroud)

我想我可以通过启动 grep 命令的目录中的文件将拆分输出到目录循环中——但是如何优雅而简洁地做到这一点(使用并行)?

Ole*_*nge 5

您可能不需要临时文件,因为您是从 STDIN 读取的。所以真的没有理由使用split. 使用--pipe以下方法删除文件:

cat words | parallel --pipe -L 1000 -N1 ./script.sh
Run Code Online (Sandbox Code Playgroud)

如果它真的只是你想要的 grep:

find dir-with-5000-files -type f | parallel -X grep -f words.txt 
Run Code Online (Sandbox Code Playgroud)

如果words.txt太大而无法放入内存,您可以将其拆分:

find dir-with-5000-files -type f | parallel -X "cat words.txt | parallel --pipe grep -f -"
Run Code Online (Sandbox Code Playgroud)

GNU Parallel 的手册页介绍了如何最有效地为 m 个正则表达式 grep n 行:http : //www.gnu.org/software/parallel/man.html#example__grepping_n_lines_for_m_regular_expressions_

为大量正则表达式 grep 大文件的最简单解决方案是:

grep -f regexps.txt bigfile
Run Code Online (Sandbox Code Playgroud)

或者,如果正则表达式是固定字符串:

grep -F -f regexps.txt bigfile
Run Code Online (Sandbox Code Playgroud)

有两个限制因素:CPU 和磁盘 I/O。CPU 很容易衡量:如果 grep 占用 >90% 的 CPU(例如在运行 top 时),那么 CPU 是一个限制因素,并行化将加快这一过程。如果不是,则磁盘 I/O 是限制因素,并且根据磁盘系统,并行化可能更快或更慢。确定的唯一方法是测量。

如果 CPU 是限制因素,则应在正则表达式上进行并行化:

cat regexp.txt | parallel --pipe -L1000 --round-robin grep -f - bigfile
Run Code Online (Sandbox Code Playgroud)

这将为每个 CPU 启动一个 grep 并为每个 CPU 读取一次大文件,但由于这是并行完成的,因此除了第一次读取之外的所有读取都将缓存在 RAM 中。根据 regexp.txt 的大小,使用 --block 10m 而不是 -L1000 可能会更快。如果 regexp.txt 太大而无法放入 RAM,请删除 --round-robin 并调整 -L1000。这将导致 bigfile 被读取更多次。

一些存储系统在并行读取多个块时性能更好。对于某些 RAID 系统和某些网络文件系统,情况确实如此。要并行读取 bigfile:

parallel --pipepart --block 100M -a bigfile grep -f regexp.txt
Run Code Online (Sandbox Code Playgroud)

这会将 bigfile 拆分为 100MB 的块并在每个块上运行 grep。要并行读取 bigfile 和 regexp.txt,请使用 --fifo 将两者结合起来:

parallel --pipepart --block 100M -a bigfile --fifo cat regexp.txt \
\| parallel --pipe -L1000 --round-robin grep -f - {}
Run Code Online (Sandbox Code Playgroud)


Jos*_* R. 4

您可以使用该split工具:

split -l 1000 words.txt words-
Run Code Online (Sandbox Code Playgroud)

将把你的words.txt文件分割成多个文件,每个文件的命名不超过 1000 行

words-aa
words-ab
words-ac
...
words-ba
words-bb
...
Run Code Online (Sandbox Code Playgroud)

如果省略前缀(words-在上面的示例中),split则用作x默认前缀。

要使用生成的文件,parallel您可以使用 glob:

split -l 1000 words.txt words-
parallel ./script.sh ::: words-[a-z][a-z]
Run Code Online (Sandbox Code Playgroud)