Bash 如何分割文件并并行处理它们,然后将它们缝合回去?unix

Bash 如何分割文件并并行处理它们,然后将它们缝合回去?unix,bash,perl,unix,split,cat,Bash,Perl,Unix,Split,Cat,我有一个文本文件infle.txt: abc what's the foo bar. foobar hello world, hhaha cluster spatio something something. xyz trying to do this in parallel kmeans you're mean, who's mean? 文件中的每一行都将由这个perl命令处理到out.txt文件中 `cat infile.txt | perl dosomething > out.tx

我有一个文本文件
infle.txt

abc what's the foo bar.
foobar hello world, hhaha cluster spatio something something.
xyz trying to do this in parallel
kmeans you're mean, who's mean?
文件中的每一行都将由这个perl命令处理到out.txt文件中

`cat infile.txt | perl dosomething > out.txt`
想象一下,如果文本文件是100000000行。我想并行化bash命令,所以我尝试了以下方法:

$ mkdir splitfiles
$ mkdir splitfiles_processed
$ cd splitfiles
$ split -n3 ../infile.txt
$ for i in $(ls); do "cat $i | perl dosomething > ../splitfiles_processed/$i &"; done
$ wait
$ cd ../splitfiles_processed
$ cat * > ../infile_processed.txt

但是有没有一种不那么冗长的方法可以做到这一点呢?

我自己从来没有试过,但可能值得一试

下面是手册页的一段摘录(
parallel(1)
),与您当前正在做的工作类似。它还可以以其他方式分割输入

EXAMPLE: Processing a big file using more cores To process a big file or some output you can use --pipe to split up the data into blocks and pipe the blocks into the processing program. If the program is gzip -9 you can do: cat bigfile | parallel --pipe --recend '' -k gzip -9 >bigfile.gz This will split bigfile into blocks of 1 MB and pass that to gzip -9 in parallel. One gzip will be run per CPU core. The output of gzip -9 will be kept in order and saved to bigfile.gz 示例:使用更多内核处理大文件 要处理大文件或某些输出,可以使用--pipe进行拆分 将数据分成块,并通过管道将块送入处理程序。 如果程序是gzip-9,则可以执行以下操作: cat bigfile | parallel--pipe--recend'-k gzip-9>bigfile.gz 这将把大文件分成1MB的块,并将其传递给gzip-9 同时。每个CPU核心将运行一个gzip。gzip-9的输出 将保持有序并保存到bigfile.gz 这是否值得,取决于处理的CPU密集程度。对于简单的脚本,您将花费大部分时间将数据从磁盘转移到磁盘,而并行化不会给您带来太多好处


您可以找到GNU并行作者的一些介绍性视频。

假设您的限制因素不是您的磁盘,您可以在perl中使用
fork()
实现这一点,特别是:

#/usr/bin/perl
严格使用;
使用警告;
使用并行::ForkManager;
我的$max_forks=8#2个进程通常是最佳的
子过程线{
#用这条线做点什么
}
my$fork\u manager=Parallel::ForkManager->new($max\u forks);

open(my$input,“来自@Ulfalizer的答案为您提供了一个关于解决方案的好提示,但缺少一些细节

您可以在Debian上使用(
apt get install parallel

因此,可以使用以下命令解决您的问题:

parallel -a infile.txt -l 1000 -j 10 -k --spreadstdin perl dosomething > result.txt
以下是这些论点的含义:

-a: read input from file instead of stdin
-l 1000: send 1000 lines blocks to command
-j 10: launch 10 jobs in parallel
-k: keep sequence of output
--spreadstdin: sends the above 1000 line block to the stdin of the command

为什么要拆分它呢?还有一个
cat
滥用问题。
perl
可以进行适当的修改,也可以制作备份副本。听起来像是XY问题。你真正想解决的问题是什么,导致你想使用这种类型的解决方案?将
cat…|
视为
#做点什么
。我需要将一个文件拆分为多个部分进行处理,然后将处理过的部分缝合回一个文件。我无法控制
#do something
,因此我向它提供一个文本文件,它将输出一个处理过的文本文件。您已经找到了一个可行的解决方案。您可能找不到更简单的MAP/REDUCE.8行shell的实现代码不是一个冗长的解决方案。我喜欢Parallel::ForkManager,但不是一次处理一行。处理文件的一个碎片-是的,一行-不,太多的fork或verhead。它复制了OP的请求。但是,是的,它更取决于每行需要多少“努力”。
fork
是非常轻量级的,但是-and是任何一种gnu并行风格的操作都会发生的事情。Fork不是轻量级的。它是最重的。最重的是什么?您调用的每个进程都是Fork和exec。因此它非常好。在Unix上进行了优化。每个系统都已经存在了几十年,它们仍然有相对成本,Fork/exec是其中最高的这就是为什么在优化web堆栈时,它是第一个被消除的东西。谢谢Adam!为了分散这些点,如果没有问题的话,选中标记会出现在您的身上,@Ulfalizer会得到赏金=)非常棒的平行结果
-a: read input from file instead of stdin
-l 1000: send 1000 lines blocks to command
-j 10: launch 10 jobs in parallel
-k: keep sequence of output
--spreadstdin: sends the above 1000 line block to the stdin of the command