为什么 GNU 并行不能与“bash -c”一起工作?

为什么 GNU 并行不能与“bash -c”一起工作?
% echo -e '1\n2' | parallel "bash -c 'echo :\$1' '' {}"
:1
:2
% echo -e '1\n2' | parallel bash -c 'echo :\$1' '' {}


%

我希望第二行的行为相同。

答案1

parallel已经在 shell 中运行命令(通过parallel使用启发式方法确定是哪个 shell(其目的是调用与parallel调用的shell 相同的 shell))。您可以设置该$PARALLEL_SHELL变量来修复 shell)。

它不是您传递给or命令parallel的命令,而是一个 shell 命令行(就像您传递给命令的那样)。envxargseval

与 for 一样eval,inparallel arg1 arg2parallel将这些参数与中间的空格连接起来(因此它变成arg1 arg2),并将该字符串传递给<the-shell> -c

parallel对于在的 stdin上传递的参数,以特定 shell 期望的格式引用它们(这是一项困难且容易出错的任务,这就是为什么您会发现在的 Changelogparallel中修复了很多错误(parallel一些截至 2017-03-06 仍未修复))并将其附加到该命令行。

例如,如果从内部调用bash

echo "foo'bar" | parallel echo foo

将与命令行并行bash -c调用echo foo foo\'bar。如果从内部rc(或使用PARALLEL_SHELL=rc)调用rc -cwith echo foo foo''''bar

在你的:

parallel bash -c 'echo :\$1' '' {}

parallel连接这些参数给出:

bash -c echo :$1  {}

并且以{}您调用的 shell 的正确格式进行扩展和引用parallel,将其传递给<that-shell> -c将使用bash -c echoin:$1$0当前参数进行调用的 shell $1

事情不是这样的parallel。在这里,您可能想要:

printf '1\n2\n' | PARALLEL_SHELL=bash parallel 'echo :{}'

要查看它的parallel作用,您可以在strace -fe execve(或者如果不是 Linux,则在您的系统上的等效系统)下运行它。

在这里,您可以使用 GNUxargs而不是parallel获得更接近您期望的更简单的处理:

printf '1\n2\n' | xargs -rn1 -P4 bash -c 'echo ":$1"' ''

另请参阅以下讨论:https://lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html

请注意,在 中bash -c 'echo foo' '' foo,您正在$0为该内联脚本创建空字符串。我会避免这种情况,因为它$0也用在错误消息中。比较:

$ bash -c 'echo x > "$1"' '' /
: /: Is a directory

和。

$ bash -c 'echo x > "$1"' bash /
bash: /: Is a directory

bash另请注意,不加引号的变量在和中具有非常特殊的含义,echo通常不能用于任意数据。

相关内容