如何初始化脚本变量

如何初始化脚本变量

我有一个文件,其中有一些可供脚本使用的函数。
所以在我的脚本中我执行以下操作:

source my_functions.sh   

VALUE_A=$(get_proper_value "X")  
[[ -z "$VALUE_A" ]] && echo "Missing value" && exit 1  

THE_URL=$(get_url_of_service "SERVICE_NAME")  
[[ -z "$THE_URL" ]] && echo "Missing URL" && exit 1    

CUSTOMER_ID=$(generate_customer_id "Z")  
[[ -z "$CUSTOMER_ID" ]] && echo "Missing customer id" && exit 1      

etc  

在实际进行任何处理之前,我的脚本顶部还有 4-5 个这样的声明。
这似乎使脚本变得混乱。

对此有更好的方法吗?我正在考虑声明里面的变量my_functions.sh,但我想知道这是否会使情况变得更糟,因为不清楚这些变量来自哪里

答案1

不,你正在做的是一种称为“保护条款”这是一件好事。稍后在代码中处理这些微不足道的错误情况可能会使代码变得比必要的更加复杂。

答案2

好吧,当然有一些方法可以使测试更简短,例如将重复部分放在函数中

notempty() { for val; do [ -z "$val" ] && return 1; done; return 0; }

VALUE_A=$(...)
THE_URL=...
CUSTOMER_ID=...  
notempty "$VALUE_A" "$THE_URL" "$CUSTOMER_ID" || { echo required variable not set >&2; exit 1; }

但这并不能让您为每个变量提供自定义错误消息。滥用间接引用至少打印变量的名称怎么样?

notempty_ind() { 
    for var; do 
        if [ -z "${!var}" ]; then 
            echo "variable $var not set!" >&2; 
            return 1;
        fi;
    done; 
    return 0; 
}
...  
notempty_ind VALUE_A THE_URL CUSTOMER_ID || exit 1

或者只是将ifs 替换为${parameter:?message}扩展 @ Kusalananda提及。如果未设置或为空,它将退出 shell 并打印一条错误消息parameter。 (参见例如Bash 手册

CUSTOMER_ID=...
: "${CUSTOMER_ID:?customer id not set!}" "${THE_URL:?}"

Bash 的错误消息包含变量名称,因此如果名称足够清晰,则实际上并不需要自定义消息。

答案3

我能想到的一些事情可以让主脚本变得不那么混乱。

  1. 如果无法确定值,请使用 使您的函数返回非零退出代码return 1。或者,让它们实际上终止该脚本使用exit.

    让它们返回非零退出状态可以与使用名称引用变量配合使用:

    set -e
    
    generate_customer_id CUSTOMER_ID "Z"
    

    这里我们假设generate_customer_id将要设置的变量的名称作为第一个参数(它将typeset -n var="$1"在其代码中使用并var=...something...在返回之前设置)。如果它无法获取第二个参数的客户 ID,则会return 1。然后主脚本将由于以下原因退出set -e(这使得 shell 在命令返回非零时立即退出)。

  2. 除了上述内容之外,或者可能代替上述内容,请使用set -u.一旦您尝试扩展当前未设置的变量的值,这将使脚本立即退出。

答案4

跟进 @xenoid 和 @ilkkachu 的答案,使用最新版本的 bash,您可以使用名称引用变量在函数中

guard_var() {
    local -n var=$1    
    local value=$2
    local desc=$3

    if [[ $value ]]; then
        var=$value
    else
        echo "Missing $desc"
        exit 1
    fi
}

guard_var  valueA      "$(get_proper_value "X")"               "value"
guard_var  theUrl      "$(get_url_of_service "SERVICE_NAME")"  "URL"
guard_var  customerId  "$(generate_customer_id "Z")"           "customer id"

并且guard_var可以将该函数放置在 my_functions.sh 文件中以将其从脚本中取出。

相关内容