我知道,鉴于l="a b c"
,
echo $l | xargs ls
产量
ls a b c
哪个构造产生
mycommand -f a -f b -f c
答案1
一种方法是:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
这假设a
, b
, 且不c
包含空格、换行符、引号或反斜杠。 :)
使用 GNU,findutil
您可以处理一般情况,但稍微复杂一些:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
您可以将分隔符替换为、或|
中未出现的其他字符。a
b
c
编辑:作为@迈克尔莫尔请注意,如果参数列表很长,则存在溢出可传递给的参数最大长度的风险mycommand
。当发生这种情况时,最后一个xargs
将拆分列表并运行 的另一个副本mycommand
,并且存在留下未终止的 的风险-f
。如果您担心这种情况,可以将xargs -0
上面的最后一个替换为如下所示:
... | xargs -x -0 mycommand
这不能解决问题,但当mycommand
参数列表太长时,它会中止运行。
答案2
解决这个问题的更好方法(IMO)是:
在
zsh
:l=(a b c) mycommand -f$^l
或使用数组压缩,以便参数不附加到选项:
l=(a b c) o=(-f) mycommand "${o:^^l}"
这样,如果
l
数组包含空元素或包含空格或任何其他有问题的字符的元素,它仍然有效xargs
。例子:$ l=(a '' '"' 'x y' c) o=(-f) $ printf '<%s>\n' "${o:^^l}" <-f> <a> <-f> <> <-f> <"> <-f> <x y> <-f> <c>
在
rc
:l=(a b c) mycommand -f$l
在
fish
:set l a b c mycommand -f$l
(AFAIK,rc
并且fish
没有数组压缩)
使用类似 Bourne 的旧式 shell bash
,您始终可以这样做(仍然允许数组元素中的任何字符$@
):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
答案3
为参数添加前缀的最简单方法是通过printf
与命令替换:
l="a b c"
mycommand $(printf ' -f %s' $l)
$()
或者,可以通过管道重写命令替换xargs
:
printf ' -f %s' $l | xargs mycommand
命令替换允许控制动态参数在参数列表中的位置。例如,您可以在前面添加、追加参数,甚至将参数放置在要传递给 的任何其他固定参数之间的任意位置mycommand
。
该xargs
方法最适合将参数附加到末尾,但它需要更晦涩的语法来处理固定参数之间动态参数的不同放置。
答案4
前置-f
:
echo 'a b c' | xargs -n 1 echo -e -f | xargs mycommand
-e 参数是为了避免 -f 被解释为另一个参数
如果您想要像这样的输出(a、b 和 c 均位于 -f 和 a -g 之间):
mycommand -f a -g -f b -g -f c -g
那么命令将是这样的:
echo 'a b c' | tr ' ' '\n' | xargs -I @ echo -e -f @ -g | xargs mycommand