【问题标题】:GNU Parallel produces different output compared to while loop with this sed command与使用此 sed 命令的 while 循环相比,GNU Parallel 产生不同的输出
【发布时间】:2015-04-19 22:46:17
【问题描述】:

我对 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 循环行为有什么想法吗?

谢谢!

【问题讨论】:

  • 您希望多个并行seds 就地修改单个文件?

标签: bash sed while-loop parallel-processing gnu-parallel


【解决方案1】:

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

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

如果您觉得这比仅使用显式 tmp 文件更好,可以在 GNU awk 中使用 -i inplace。

【讨论】:

  • 这是一个漂亮的 awk 单行。我正在玩的文件的运行时间非常快。感谢您的解决方案。我知道,原则上,单线不会通过所有不必要的 sed 循环。但是,你能解释一下是什么让这个 awk 命令这么快吗?
  • shell 被设计为(因此被优化为)一个调用 UNIX 工具的环境,而不是一个操作文本的工具。 awk 被设计为(因此被优化为)用于操作文本的 UNIX 工具。这只是为每项工作使用正确工具的情况。
【解决方案2】:

这是由于 sed 没有替换到位。它的作用是创建一个新文件,然后将其移动到原始文件中。

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

所以如果你使用-j1 你不会看到这个问题。但是您也不会看到速度加快。

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

【讨论】:

  • 感谢您的洞察力。看来我的方法不是处理这项任务的好方法。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2021-02-04
    • 2019-01-11
    • 2023-03-30
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多