我有一个文件,其中有一些可供脚本使用的函数。
所以在我的脚本中我执行以下操作:
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
或者只是将if
s 替换为${parameter:?message}
扩展 @ Kusalananda提及。如果未设置或为空,它将退出 shell 并打印一条错误消息parameter
。 (参见例如Bash 手册)
CUSTOMER_ID=...
: "${CUSTOMER_ID:?customer id not set!}" "${THE_URL:?}"
Bash 的错误消息包含变量名称,因此如果名称足够清晰,则实际上并不需要自定义消息。
答案3
我能想到的一些事情可以让主脚本变得不那么混乱。
如果无法确定值,请使用 使您的函数返回非零退出代码
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 在命令返回非零时立即退出)。除了上述内容之外,或者可能代替上述内容,请使用
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 文件中以将其从脚本中取出。