为什么 xargs 会用空格分割,甚至用 -0 分割?

为什么 xargs 会用空格分割,甚至用 -0 分割?

根据互联网上的文档和建议,以下任何一种:

$ ls $(env -0 | xargs -0)
$ ls $(env | xargs -d '\n')

给定LESSOPEN应该| %s _=/usr/bin/env产生这个:

...
ls: cannot access 'LESSOPEN=| %s _=/usr/bin/env': No such file or directory

但实际上我得到的是:

...
ls: cannot access 'LESSOPEN=|': No such file or directory
ls: cannot access '%s': No such file or directory
ls: cannot access '_=/usr/bin/env': No such file or directory

为什么即使有选择它仍然会在空格处分割-0

系统:Ubuntu 18.04.3 LTS。


笔记。我使用ls只是为了揭露论点。我的最终目标是这样的:

docker exec node_container env $(env -0 | grep -z '^SOME_PREFIX_' | xargs -0) yarn build

答案1

不,它不会按空格分割。贝壳将 $(…) 扩展的输出按空格分割,当以这种方式使用时,xargs 对此无能为力。

如果你不将任何 $variable 或 $(command) 扩展括起来,则 shell 将总是将结果值按空格/制表符/换行符拆分为单个单词。无论您的“内部”命令是 $(xargs) 还是 $(anything else),其输出都会被 shell 以相同的方式重新解释。

换句话说,这不是您应使用 xargs 的方式。Xargs 只有在以下情况下才能正常工作:本身允许构建最终的命令行,如下所示:

env -0 | xargs -0 ls

Xargs 不知道如何在中间插入多个参数(默认情况下它只能附加,并且-I只能插入一个)。因此,在您的情况下,所有“尾随”参数都必须作为 xargs 的一部分提供输入

(env -0 | grep -z "^SOME_PREFIX_";
 printf "yarn\0build\0") | xargs -0 docker exec node_container env

但此时最好尝试非基于 xargs 的方法:

#!/usr/bin/env bash
# This example uses Bash-specific features and won't work with plain sh
args=()
for key in ${!SOME_PREFIX_*}; do
    args+=("$key=${!key}")
done
docker exec node_container env "${args[@]}" yarn build

请注意,在最后一个示例中,“args[@]”是一个数组变量,因此双引号括住它的扩展将正确地为每个数组项生成一个参数,而无需任何空格分割。(困难的部分实际上是获取一些命令的输出进入数组。幸运的是,您可以使用 shell 内部工具收集环境变量,而无需外部命令。

非 shell 语言也可以完成这个工作:

#!/usr/bin/env perl
@cmd = qw(docker exec node_container env),
       (map {"$_=$ENV{$_}"} grep {/^SOME_PREFIX_/} keys %ENV),
       qw(yarn build);
system @cmd;

答案2

你想做的事情可以通过以下方式实现:

env -0 | xargs -0 ls 

答案3

我不知道这个答案是否适合你,但是我发现这个: 使用 xargs

相关内容