使用 xargs --max-args --replace 为默认分隔符时出现问题

使用 xargs --max-args --replace 为默认分隔符时出现问题

这按预期工作:

$ echo a b c | xargs --replace="{}" echo x "{}" y
x a b c y

这也可以:

$ echo a b c | xargs --max-args=1 echo x
x a
x b
x c

但这并没有按预期工作:

$ echo a b c | xargs --max-args=1 --replace="{}" echo x "{}" y
x a b c y

这也不是:

$ echo a b c | xargs --delimiter=' ' --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c
 y

我期望这个输出:

x a y
x b y
x c y

作为解决方法,我使用 printf 和两个 xargs,但这很丑陋:

$ echo a b c | xargs printf '%s\0' | \
> xargs --null --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c y

知道为什么会发生这种情况吗?

答案1

根据POSIX 文档xargs应该运行给定的实用程序,参数由空格或换行符分隔,这就是您的前两个示例中发生的情况。

但是,当使用--replace(或) 时,只有换行符会分隔参数。补救措施是在单独的行中-I给出参数:xargs

$ printf '%s\n' a b c | xargs --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c y

使用 POSIX 选项:

printf '%s\n' a b c | xargs -n 1 -I "{}" echo x "{}" y

在这里,我xargs不是一行,而是三行。它(最多)只需要一行,并以该行作为参数执行实用程序。

另请注意,上面的-n 1(或--max-args=1) 是不需要的,因为它的替换数量-I决定了所使用的参数数量:

$ printf '%s\n' a b c | xargs -I "{}" echo x "{}" y
x a y
x b y
x c y

事实上,POSIX 规范的基本原理部分xargs说(我的重点)

-I-L和选项-n是互斥的。如果在命令行上给出了多个,则某些实现会使用最后指定的一个;其他实现以不同的方式处理选项的组合。

在测试时,我注意到 OpenBSD 的版本如果和一起使用,xargs将会执行以下操作:-n-I

$ echo  a b c | xargs -n 1  -I "{}" echo x "{}" y
x a y
x b y
x c y

这与 GNU coreutilsxargs所做的不同(它产生x a b c y)。这是因为-n尽管-I使用了,但实现仍接受空格作为参数分隔符。因此,不要将-Iand-n一起使用(无论如何都不需要)。

答案2

--max-args我发现的一项解决方法是将的输出提供给--replace这样的:

echo a b c | xargs -n 1 | xargs -i echo firstPart {} secondPart

这样就会输出。

firstPart a secondPart
firstPart b secondPart
firstPart b secondPart

我想它基本上是循环输入--max-args并默认添加新行字符。

相关内容