xargs - 为每个参数附加一个参数

xargs - 为每个参数附加一个参数

我知道,鉴于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

您可以将分隔符替换为、或|中未出现的其他字符。abc

编辑:作为@迈克尔莫尔请注意,如果参数列表很长,则存在溢出可传递给的参数最大长度的风险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

相关内容