sed 与 parallel --jobs 选项的正确用法是什么?

What's the correct usage of sed with parallel --jobs option?

parallel -a input --colsep ' ' --jobs 100 -I {} sed -i 's/{1}/{2}/g' file

input是由space分隔的文件,其中第一列是pattern,第二列是replacement。

问题是在我 运行 命令之后,并不是所有的模式都在 file 中被替换。然后我再次 运行 相同的命令,更多的模式被替换了,但仍然不是全部。 但是,如果我将 --jobs 100 更改为 --jobs 1,它将按预期工作(但要慢得多)。

我的命令中是否缺少必要的参数?

听起来你更像是有竞争条件。如果您有多个 sed 进程写入文件,一个会赢,另一个会输。

无论如何,让多个进程处理同一个文件是非常不理想的;只需生成一个 sed 脚本,然后 运行 它一次。或者,如果您真的想要并行化,将输入文件拆分成更小的部分,运行 生成的 sed 脚本在每个并行,然后将它们连接起来你完成了。

当您的任务受到 CPU 约束时,并行处理会有所帮助,但这个任务受到 I/O 约束;您只是通过让多个进程争夺对磁盘字节的访问而造成拥塞,然后在这种情况下还争夺对同一文件的写访问权。

有很多关于如何生成sed脚本的例子;这是一个快速而肮脏的方法,但是在 sed -f - 不从标准输入读取脚本的某些平台上不起作用。

sed 's%^\([^ ]*\) \([^ ]*\)$%s///g%' input |
sed -f - file >temp  # or sed -f - -i file

我省略了 -i 选项,这样您就可以在投入使用并将其部署到生产环境之前检查它是否符合您的要求。注释掉的版本是您在确信这确实可以满足您的要求后使用的版本。

还有替换优先级的问题。如果你有 s/a/b/s/b/c/ 那么你想要有效 s/a/c/ 还是相反?如果你有 s/abc/x/s/abcdef/y/abcdef 应该总是变成 y,还是你期望的 xdef?一个常见的 hack 是按长度对替换进行排序,这样较长的总是在较短的之前执行;那么至少你知道会发生什么。

让我们假设 input 很大,file 很大。

你真的不想再读file了。

首先你需要将 input 转换成一个大的 sed 脚本。

cat input | parallel --colsep ' ' echo s/{1}/{2}/g >bigsed

正如@tripleee 所说,您可能需要对其进行排序,因此最长的源字符串排在第一位。

然后你需要将 file 拆分为每个 CPU 线程的一个块,运行 每个块上的脚本,最后按顺序追加替换的块:

parallel --pipepart -a file -k sed -f bigsed > replaced

您需要 /tmp 有足够的空闲空间 space 来包含 replaced 或将 $TMPDIR 设置为一个目录。