检查是否设置了变量,否则为默认值

Check if variables are set, and attribute a default otherwise

我有一串变量要检查,还有一串默认值,如下所示:

variables_to_check="name surname address"
variables_default_values="John Doe Paris"

这是我想做的事情:

  1. 检查是否设置了 $name,如果没有,给它 John 作为值
  2. 检查是否设置了 $surname,如果没有,给它 Doe 作为值
  3. ...

这是我当前无法使用的代码:

variables_to_check="name surname address"
variables_default_values="John Doe Paris"
i=0
for variable in $variables_to_check
do
    ((i++))
    if [[ -z ${"$variable"+x} ]] #this line doesn't seem to work
                                 #inspired from 
    then
        default=$(echo $variables_default_values | cut -d " " -f $i)
        set_config $variable $default
        declare "$variable=$default" #this doesn't seem to work either
                                     #inspired from 
    fi
done

如有任何帮助,我们将不胜感激

使用 -v 运算符确定是否设置了变量。如果您使用数组来存储名称和默认值,这也会容易得多。

variables=(name surname address)
default_values=(John Doe "somewhere in Paris")

for ((i=0; i < ${#variables[@]}; i++)); do
    if ! [[ -v ${variables[i]} ]]; then
        declare "${variables[i]}=${default_values[i]}"
    fi
done

bash -v 需要 4.3 或更高版本才能使用数组。

Namerefs(也在 4.3 中引入)可以使这更简单一些:

for ((i=0; i < ${#variables[@]}; i++)); do
    declare -n name=${variables[i]}
    [[ -v name ]] && name=${default_values[i]}"
done

除非以编程方式生成变量和默认值列表,否则一点点重复将更具可读性并且实际上不会更难维护:

# This will also work in any POSIX-compliant shell, not just
# in a sufficiently new version of bash
: ${name:=John}
: ${surname:=Doe}
: ${address:=somewhere in Paris}

shell 有一些可爱的字符串替换运算符可以做到这一点,但还有第三种可能性你没有在上面列出:变量被设置为值“”。

Expression     "var Set not Null"   "var Set but Null"  "var Unset"
${var-DEFAULT}      var                 null             DEFAULT    
${var:-DEFAULT}     var                 DEFAULT          DEFAULT
${var=DEFAULT}      var                 null             DEFAULT    
${var:=DEFAULT}     var                 DEFAULT          DEFAULT    
${var+OTHER}        OTHER               OTHER            null   
${var:+OTHER}       OTHER               null             null   

所以在你的情况下,你会想要这样的东西:

${name:-"John"}   # or ${name:="John"} 
${surname:-"Doe"} # or ${surname:="Doe"}

等等。

您可以使用 "namerefs" 来执行此操作:

variables=( a b c d e )
c=1
d=7

value=42

declare -n var

for var in ${variables[@]}; do
    if [[ ! -v var ]]; then
        var=$value
    fi
done

echo $a, $b, $c, $d, $e

运行它:

$ bash script.sh
42, 42, 1, 7, 42

在循环中,var 变量是对数组 variables 中命名变量的名称引用,这意味着您可以使用 var as 命名变量。

使用-v查看变量是否已设置,如果未设置,则为其赋值。整个 if 语句也可以替换为单行

: ${var:=$value}

: 是一个空操作命令,它计算它的参数,参数的计算有副作用,即 shell 给变量赋值 var 如果未设置)。

编辑:以下是同一件事,但每个变量都有单独的默认值:

variables=( a b c d e )
defaults=( 1 2 3 4 5 )

c=1
d=7

for (( i = 0; i < ${#variables[@]}; ++i )); do
        declare -n var="${variables[$i]}"
        value="${defaults[$i]}"

        : ${var:=$value}
done

echo $a, $b, $c, $d, $e

运行它:

$ bash script.sh
1, 2, 1, 7, 5