if [[ ${1:+isset} ]]then echo "It was set and not null." >&2else echo "It was not set or it was null." >&2fi
if [[ ${1+isset} ]]then echo "It was set but might be null." >&2else echo "It was was not set." >&2fi
if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigilthenecho "Variable is unset"elif [ -z "$SOMEVARIABLE" ]thenecho "Variable is set to an empty string"elseecho "Variable is set to some string"fi
is_var_defined(){if [ $# -ne 1 ]thenecho "Expected exactly one argument: variable name as string, e.g., 'my_var'"exit 1fi# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.# Example: $1="var"# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"# Code execute: [ ! -z ${var:-} ]eval "[ ! -z \${$1:-} ]"return $? # Pedantic.}
我跳过了test -v var、[ -v var ]和[[ -v var ]],因为它们产生的结果与POSIX标准[ -n "${var+x}" ]相同,同时需要Bash 4.2+。我还跳过了typeset -p,因为它与我测试过的shell中的declare -p相同(Bash 3.0到5.0,和Zsh 5.5.1)。
is-var-set-after() {# Set var by passed expression.unset vareval "$1"
# Run the tests, in increasing order of accuracy.[ -n "$var" ] # (index 0 of) var is nonemptynonempty=$?[ -n "${var+x}" ] # (index 0 of) var is set, maybe emptyplus=$?[ "${#var[@]}" != 0 ] # var has at least one index set, maybe emptycount=$?declare -p var &>/dev/null # var has been declared (any type)declared=$?
# Show test results.printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared}
# Header.printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.is-var-set-after "var=foo" # 0 0 0 0is-var-set-after "var=(foo)" # 0 0 0 0is-var-set-after "var=([0]=foo)" # 0 0 0 0is-var-set-after "var=([x]=foo)" # 0 0 0 0is-var-set-after "var=([y]=bar [x]=foo)" # 0 0 0 0# '[ -n "$var" ]' fails when var is empty.is-var-set-after "var=''" # 1 0 0 0is-var-set-after "var=([0]='')" # 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.is-var-set-after "var=([1]='')" # 1 1 0 0is-var-set-after "var=([1]=foo)" # 1 1 0 0is-var-set-after "declare -A var; var=([x]=foo)" # 1 1 0 0# Empty arrays are only detected by 'declare -p'.is-var-set-after "var=()" # 1 1 1 0is-var-set-after "declare -a var" # 1 1 1 0is-var-set-after "declare -A var" # 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.is-var-set-after "unset var" # 1 1 1 1
# The first ! negates the result (can't use -n to achieve this)# the second ! expands the content of varname (can't do ${$varname})function IsDeclared_Tricky{local varname="$1"! [ -z ${!varname+x} ]}
# The first parameter needs to be the name of the variable to be checked.# (See example below)
var_is_declared() \{\{ [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}}
var_is_unset() \{\{ [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;}}
通过首先测试变量是否设置(un),如果没有必要,可以避免调用声明。
但是,如果$1包含一个空的$array=()的名称,则调用声明将确保我们得到正确的结果
从来没有多少数据传递给 /dev/null因为只有在变量未设置或空数组时才会调用声明。
此函数将在以下条件下进行测试:
a; # is not declareda=; # is declareda="foo"; # is declareda=(); # is declareda=(""); # is declaredunset a; # is not declared
a; # is unseta=; # is not unseta="foo"; # is not unseta=(); # is not unseta=(""); # is not unsetunset a; # is unset
#!/usr/bin/env bash
set -o errexit
# Get the value and empty validation check all in oneVER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
这在运行时返回一个错误
peek@peek:~$ ./setver.sh./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument
仅选中,没有退出-空和未设置无效
如果您只想检查值set=VALID或unset/空=INVALID,请尝试此选项。
TSET="good val"TEMPTY=""unset TUNSET
if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi# VALIDif [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi# INVALIDif [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi# INVALID
if test "${name+x}"; thenecho 'name is set'elseecho 'name is not set'fi
这个问题已经有了很多答案,但没有一个提供善意布尔表达式来清楚地区分变量值。
以下是我想出的一些明确的表达方式:
+-----------------------+-------------+---------+------------+| Expression in script | name='fish' | name='' | unset name |+-----------------------+-------------+---------+------------+| test "$name" | TRUE | f | f || test -n "$name" | TRUE | f | f || test ! -z "$name" | TRUE | f | f || test ! "${name-x}" | f | TRUE | f || test ! "${name+x}" | f | f | TRUE |+-----------------------+-------------+---------+------------+
H="+-%s-+-%s----+-%s----+-%s--+\n" # table divider printf formatR="| %-10s | %-10s | %-10s | %-10s |\n" # table row printf format
S='V' # S is a variable that is set-and-not-nullN='' # N is a variable that is set-but-null (empty "")unset U # U is a variable that is unset
printf "$H" "----------" "-------" "-------" "---------";printf "$R" "expression" "FOO='V'" "FOO='' " "unset FOO";printf "$H" "----------" "-------" "-------" "---------";printf "$R" "\${FOO:-x}" "${S:-x}" "${N:-x}" "${U:-x} "; S='V';N='';unset Uprintf "$R" "\${FOO-x} " "${S-x} " "${N-x} " "${U-x} "; S='V';N='';unset Uprintf "$R" "\${FOO:=x}" "${S:=x}" "${N:=x}" "${U:=x} "; S='V';N='';unset Uprintf "$R" "\${FOO=x} " "${S=x} " "${N=x} " "${U=x} "; S='V';N='';unset U# "${N:?x}" "${U:?x} "printf "$R" "\${FOO:?x}" "${S:?x}" "<error>" "<error> "; S='V';N='';unset U# "${U?x} "printf "$R" "\${FOO?x} " "${S?x} " "${N?x} " "<error> "; S='V';N='';unset Uprintf "$R" "\${FOO:+x}" "${S:+x}" "${N:+x}" "${U:+x} "; S='V';N='';unset Uprintf "$R" "\${FOO+x} " "${S+x} " "${N+x} " "${U+x} "; S='V';N='';unset Uprintf "$H" "----------" "-------" "-------" "---------";
以及运行脚本的输出:
+------------+------------+------------+------------+| expression | FOO='V' | FOO='' | unset FOO |+------------+------------+------------+------------+| ${FOO:-x} | V | x | x || ${FOO-x} | V | | x || ${FOO:=x} | V | x | x || ${FOO=x} | V | | x || ${FOO:?x} | V | <error> | <error> || ${FOO?x} | V | | <error> || ${FOO:+x} | x | | || ${FOO+x} | x | x | |+------------+------------+------------+------------+