Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash:将数组中的每个项转换为带有标志的命令参数_Bash - Fatal编程技术网

Bash:将数组中的每个项转换为带有标志的命令参数

Bash:将数组中的每个项转换为带有标志的命令参数,bash,Bash,假设我们有一个数组FOO=(“hello world”“xyzy”)。我们希望运行thing工具,将$FOO的每个元素作为单独的-Z标志传递,从而生成以下命令: thing -Z "hello world" -Z "xyzzy" 这些方法不起作用: # Equivalent to `thing "-Z hello world" "-Z xyzzy"` thing "${FOO[@]/#/-Z }" # Equivalent to `thing "-Z hello world -Z xyzzy

假设我们有一个数组
FOO=(“hello world”“xyzy”)
。我们希望运行
thing
工具,将
$FOO
的每个元素作为单独的
-Z
标志传递,从而生成以下命令:

thing -Z "hello world" -Z "xyzzy"
这些方法不起作用:

# Equivalent to `thing "-Z hello world" "-Z xyzzy"`
thing "${FOO[@]/#/-Z }"

# Equivalent to `thing "-Z hello world -Z xyzzy"`
thing "${FOO[*]/#/-Z }"

# Equivalent to `thing -Z hello world -Z xyzzy`
thing ${FOO[@]/#/-Z }

# Equivalent to `thing -Z hello world -Z xyzzy`
thing ${FOO[*]/#/-Z }
我可以做的是在数组的每个元素之间插入一个
-Z

FOO2=()
for x in "${FOO[@]}"; do FOO2+=("-Z" "$x"); done
thing "${FOO2[@]}"
有没有一种不需要显式循环和数组副本的方法?

使用
bash
≥ 4.4 您可以使用空字节分隔符(
\0
)打印数组,在每个条目前面插入
-Z\0
,然后再次将结果作为数组读取:

以下解决方案需要
bash
≥ 4.4由于
映射文件-d
。另一种选择,请参见本答案末尾的hack

processargs() {
   (( "$#" )) && printf -- '-Z\0%s\0' "$@"
}
array=('' 1 ' x y ' $'multiline\ntext')
mapfile -d '' arrayWithZ < <(processargs "${array[@]}")
对于空数组,我们不插入任何
-Z
。如果
array=()
那么
arrayWithZ=()

使用
eval
,尤其是对于
bash
<4.4 如果不需要显式数组
arrayWithZ
,那么可以使用以下方法。即使在这种情况下,
eval
应该是安全的,我还是建议不要使用它——也许我确实监督了一些事情。但是,当您被困在
bash
<4.4中时,这种攻击可能很有用,因为不再需要
mapfile-d

processargs() {
   (( "$#" )) && printf -- '-Z %q ' "$@"
}
array=('' 1 ' x y ' $'multiline\ntext')
eval "yourCommand $(processargs "${array[@]}")"

虽然没有做出明确的声明,但我会注意到显式循环就是我所做的。如果工具允许参数直接附加到
-Z
(即
thing“-Zhello world”“-Zxyzzy”
),那么您可以使用
thing“${FOO[@]/#/-Z}”
。否则,我认为您需要使用循环。我喜欢@GordonDavidson的建议,因为许多GNU风格的工具将通过它们的长选项来支持这一点,例如
sed-efoo-ebar
=>
sed--expression=foo--expression=bar
您可以使用
printf--'-Z\0%s\0'$@
来避免通过
sed
,但这实际上只是一种更复杂的方法,可以创建一个插入了额外参数的数组副本。@thatotherguy很好!这不仅更短,而且可以在BSD上运行。我根据你的建议编辑了我的答案。
processargs() {
   (( "$#" )) && printf -- '-Z %q ' "$@"
}
array=('' 1 ' x y ' $'multiline\ntext')
eval "yourCommand $(processargs "${array[@]}")"