通过 xargs 传递多个参数

Dam*_*yer 25 xargs

我希望能够xargs在命令的不同部分执行多个参数。

例如,以下内容:

echo {1..8} | xargs -n2 | xargs -I v1 -I v2 echo the number v1 comes before v2
Run Code Online (Sandbox Code Playgroud)

我希望它会回来

the number 1 comes before 2
the number 3 comes before 4 
Run Code Online (Sandbox Code Playgroud)

... 等等

这是可以实现的吗?我怀疑我的多次使用-I是不正确的。

Sco*_*ott 43

我相信你不能这样使用-I。但是你可以通过说你想要的效果?/?行为:

echo {1..8} | xargs -n2 sh -c 'echo "the number $1 comes before $2"' sh
Run Code Online (Sandbox Code Playgroud)

这实质上创建了一个临时的单行 shell 脚本,该xargs脚本通过sh -c. xargs从输入中解析出来的两个值被传递给这个“脚本”。然后外壳将这些值分配给$1$2,然后您可以在“脚本”中引用它们。

  • @DamienSawyer 没有第二次调用`sh`。最后尾随的 `sh` 是放入 `$0` 的内容。`$0` 通常保存解释器或脚本的名称。 (8认同)
  • 谢谢 - 那太好了。我一直在为 sh 阅读 man 并且正在努力理解对 sh 的第二个调用的作用,以及为什么它的省略会产生“一半”的结果。 (5认同)
  • 我没有得到关于尾随 `sh` 的解释,但运行 `xargs --verbose` 使它更清楚:传递的尾随值作为 `$0` 环境变量输入到 `sh -c` 执行中。因此,如果您的脚本不使用“$0”,您可以传递任何内容。习惯上传递“sh”。并且需要它,以便 xargs 可以输出其他参数(您首先需要 `$0` 来输出 `$1`、`$2`...替换)。示例: `sh -c 'echo $1/$2/$0' sh AB` 写入 `A/B/sh` (有关 `$0` 的更多信息:https://bash.cyberciti.biz/guide/$0) (5认同)

Sté*_*las 6

在 的特定情况下printf,您始终可以执行以下操作:

echo {1..8} | xargs printf 'the number %s comes before %s\n'
Run Code Online (Sandbox Code Playgroud)

因为如果给定的参数多于单次调用所需的参数,则它具有类似printf内在xargs的能力,可以多次执行。虽然这没有什么优势

printf 'the number %s comes before %s\n' {1..8}
Run Code Online (Sandbox Code Playgroud)

对于大型列表,简单的xargs命令可能会导致xargs运行多个 实例printf,其中一些可能具有奇数个参数。您可以传递-n 1000xargs以防止出现这种情况,其中 1000 是一个偶数,它应该足够小,以免达到arg 列表过长的限制,并且足够大以避免运行如此多的printfs。

请注意,每次调用都在一个单独的新进程中xargs调用,而不是您的 shell 的 builtin printf,而是 external printf

还要注意,对于空输入,除了在某些 BSD 上,它仍然会printf在没有参数的情况下运行一次。GNUxargs和 compatible 有一个-r (或--no-run-if-empty)选项来避免这种情况。

需要明确的是,这个简单的答案特定于您的printf示例,并且在您必须一次向命令传递两个参数的一般情况下不起作用(例如,就属于这种情况diff)。要使用 解决一般问题zsh,您可以使用:

for i j ({1..8}) echo "the number $i comes before $j"
Run Code Online (Sandbox Code Playgroud)