测试是否设置了多个变量

Jas*_*per 21 bash shell-script

我想确保在脚本的某个点,在source配置文件之后,设置了几个变量,如果没有,则停止执行,告诉用户丢失的变量。我试过了

for var in $one $two $three ; do
    ...
Run Code Online (Sandbox Code Playgroud)

但是如果例如$two未设置,则永远不会为 执行循环$two。我尝试的下一件事是

for var in one two three ; do
    if [ -n ${!var} ] ; then
        echo "$var is set to ${!var}"
    else
        echo "$var is not set"
    fi
done
Run Code Online (Sandbox Code Playgroud)

但是如果没有设置两个,我仍然会得到“两个设置为”而不是“两个未设置”。

如何确保设置了所有必需的变量?

更新/解决方案:我知道“设置”和“设置,但为空”之间存在差异。我现在使用(感谢/sf/answers/1172747551/和这个问题的答案)以下内容:

if [ -n "${!var:-}" ] ; then
Run Code Online (Sandbox Code Playgroud)

所以,如果var设置了但为空,它仍然被认为是无效的。

Hau*_*ing 9

引用错误。

if [ -n "${!var}" ] ; then
Run Code Online (Sandbox Code Playgroud)

面向未来:设定

set -x
Run Code Online (Sandbox Code Playgroud)

在运行代码之前会向您展示问题。您可以使用以下命令调用脚本,而不是将其添加到代码中

bash -vx ./my/script.sh
Run Code Online (Sandbox Code Playgroud)

  • @Jasper 你应该**总是**引用变量。这并不比每次都考虑是否有必要花费更多的时间。但它避免了错误。 (4认同)
  • @mikeserv 只有单引号可以防止扩展,我显然不建议这样做。双引号可防止分词。我没有否认可能存在必须省略引用的情况。但这并不是反对我的一般规则的论据。什么样的人会使用像`set -- $(IFS=, ; echo $cs)`这样的东西?那种必须在这里问为什么`if [ -n ${!var} ] 的人;然后`不起作用?可能不是。 (2认同)

mik*_*erv 5

如果您希望程序停止:

N= 
${one?var 1 is unset} 
${two:?var 2 is unset or null}
${three:+${N:?var 3 is set and not null}}
Run Code Online (Sandbox Code Playgroud)

这样就行了。问号后面的每条消息都被打印出来,stderr父 shell就会死亡。好吧,好吧,所以不是每条消息 - 只有一条 - 只有第一个失败的消息会打印一条消息,导致 shell 死亡。我喜欢像这样使用这些测试:

( for v in "$one" "$two" "$three" ; do
    i=$((i+1)) ; : ${v:?var $i is unset or null...} 
done ) || _handle_it
Run Code Online (Sandbox Code Playgroud)

关于这个我还有很多话要说 在这里