我有带set -o nounset
选项的bash脚本(我想要那个!)。
现在,我想构造一个命令调用,但我事先并不知道参数的数量,所以我想使用一个数组(下面的例子)。但是,当ARRAY
为空数组时,"${ARRAY[@]}"
会失败。
问题:@ -expand数组("${ARRAY[@]}"
)如何在set -o nounset
开启时扩展不会失败?
示例:
# Clone git repo. Use --reference if ${reference_local_repo} exist.
reference_local_repo=.....
test -d "${reference_local_repo}" \
&& reference=("--reference" "${reference_local_repo}") \
|| reference=()
git clone "${reference[@]}" http://address/of/the/repo
当然,我可以使用以下代码:
# bad example
reference=''
test -d "${reference_local_repo}" && reference="--reference ${reference_local_repo}"
...但如果本地存储库的路径包含空格,则无效。
作为解决方法,而不是reference=()
我使用reference=("-c" "dummy.dummy=dummy")
。这样我就避免了空数组,而Bash也没有抱怨。或者,我可以(重命名数组变量和)将“clone”作为第一个数组元素。所以我得到了这个,但我想学习正确的方法。
为了记录,我正在使用GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu)
。
答案 0 :(得分:4)
我不明白为什么你在这里使用数组。你可以:
test -d "${reference_local_repo}" \
&& reference="${reference_local_repo}" \
|| reference=""
git clone ${reference:+--reference "$reference"} http://address/of/the/repo
现在没有未定义的变量,并且对于实际上是单个值的数组没有任何误解。
答案 1 :(得分:4)
回答您的具体问题:解决这个问题的原因很简单:
${reference[@]+"${reference[@]}"}
如果未设置引用,则不会扩展任何内容 如果已设置,则会扩展其所有组件。
Read the historical roots for this use:
大约20年前,如果没有参数,Bourne Shell的一些破坏的小变体将“$ @”替换为空字符串“
当然,在这个具体案例中:
test -d "${reference_local_repo}" && abool="" || unset abool
git clone ${abool+--reference "$reference_local_repo"} http://address/of/the/repo
当abool
设置为NUL(“”)时(或者如果您选择使用其他值),它会被设置,并且在下一行中它会扩展到加号后面(是的,恰好是两个参数)。
当abool
未设置时,它会在下一行扩展中完全消失。
也许这更详细:
unset abool
if test -d "${reference_local_repo}"; then abool="ValidDir"; fi
git clone ${abool+--reference "$reference_local_repo"} http://address/of/the/repo
答案 2 :(得分:-1)
您可以使用辅助变量(或只是重新定义相同的变量)来检查数组是否有任何内容:
foo=${your_array[@]:-}
然后:
git clone ... "${foo}" ...
这与nounset
标志兼容。如果:-
未定义,变量末尾的${your_array[@]:-}
扩展($your_array
)将产生一个空字符串。