与使用此 sed 命令的 while 循环相比,GNU Parallel 产生不同的输出

GNU Parallel produces different output compared to while loop with this sed command

我对 GNU Parallel 如何处理输入 sed 就地文件编辑的管道输入感到困惑,我想了解它在做什么(并且这样我才能让它工作!)。

我有两个文件,f1 和 f2,如下所示:

f1

a11    a12    a13
a21    a22    a23
...
an1    an2    an3

f2

a41
stuff
...
a91
stuff
...

我要做的是将 f1 的第二列和第三列中的元素连接到 中的每个对应元素(第一列) ]f2,使得 f2 看起来像:

a41 a42 a43
stuff
...
a91 a92 a93
things
...

一个简单的 while 循环就可以完成这项工作:

while IFS=$'\t' read -r e1 e2 e3; do sed -i "s/$e1/& $e2 $e3/g" f2 ; done < f1

我尝试使用 GNU Parallel 复制它,如下所示:

cat f1 | parallel --colsep '\t' -q sed -i "s/{1}/& {2} {3}/g" f2

与 while 循环相比,它只修改了 f2 中的一小部分条目。它看起来像这样:

a41 a42 a43
stuff
...
a91
things
...
a71 a72 a73
words
...

那么,关于正在发生的事情以及我如何使用 GNU Parallel 复制 while 循环行为有什么想法吗?

谢谢!

我知道所有这些并行的东西,但如果你只是想做一些比从 shell 循环调用的 sed 脚本更有效的事情,那么你只需要:

awk 'NR==FNR{a[]=[=10=];next} {print ( in a ? a[] : [=10=])}' f1 f2

如果您觉得这比仅使用显式 tmp 文件更好,可以将 -i 与 GNU awk 结合使用。

是sed没有原地替换的缘故。它所做的是创建一个新文件,然后将其移动到原始文件。

所以您看到的是多个 sed 并行创建一个新文件。当其中一个完成时,它将覆盖原始文件,但是当前 运行 的其他 sed 将看不到它,它们仍在处理原始文件。

因此,如果您使用 -j1,您将不会遇到此问题。但是你也不会看到加速。

我不确定 GNU Parallel 能否在这方面为您提供帮助。一个解决方案是将 f2 转换成一个大的 sed 脚本。

这里是 Ed Morton 回答的变体。这个变体说明了一种非常有用的技术并且应该(非常轻微)更快,因为它避免了检查 NR==NFR: awk -v dict=f1 'BEGIN { while (getline < dict) {a[]=[=10=]} } {print ( in a ? a[] : [=10=])}' f2