pro*_*eek 1417 variables bash shell
我如何知道Bash中是否设置了变量?
例如,如何检查用户是否将第一个参数提供给函数?
function a {
# if $1 is set ?
}
Run Code Online (Sandbox Code Playgroud)
小智 2102
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
Run Code Online (Sandbox Code Playgroud)
这里${var+x}是一个参数扩展,如果计算结果为没有var被取消设置,并替换字符串x,否则.
引号可以省略(所以我们可以说${var+x}而不是"${var+x}")因为这种语法和用法保证这只会扩展到不需要引号的东西(因为它要么扩展为x(不包含任何分词,所以它不需要引号),或者没有(导致[ -z ],方便地评估相同的值(true)[ -z "" ]也是如此)).
然而,尽管可以安全地省略引号,并且它并不是立即显而易见的(对于这个引用解释的第一作者来说,这也是一个主要的Bash编码器并不明显),编写解决方案有时会更好.引号为[ -z "${var+x}" ],以极低的O(1)速度罚款成本.第一作者还在代码旁边添加了这个注释,使用此解决方案给出了这个答案的URL,现在还包括为什么可以安全地省略引号的解释.
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
Run Code Online (Sandbox Code Playgroud)
这通常是错误的,因为它不区分未设置的变量和设置为空字符串的变量.也就是说,如果var='',则上述解决方案将输出"var is blank".
unset和"设置为空字符串"之间的区别在用户必须指定扩展名或其他属性列表并且未指定它们默认为非空值的情况下是必不可少的,而指定空字符串应该使脚本使用空扩展或其他属性列表.
但是,在每种情况下,这种区别可能并不重要.在那些情况下 [ -z "$var" ]会很好.
小智 832
要检查非null /非零字符串变量,即如果设置,请使用
if [ -n "$1" ]
Run Code Online (Sandbox Code Playgroud)
这与之相反-z.我发现自己使用的-n不仅仅是-z.
您会像以下一样使用它:
if [ -n "$1" ]; then
echo "You supplied the first parameter!"
else
echo "First parameter not supplied."
fi
Run Code Online (Sandbox Code Playgroud)
Jen*_*ens 443
以下是如何测试参数是否未设置,或者为空("Null")或使用值设置:
+--------------------+----------------------+-----------------+-----------------+
| | parameter | parameter | parameter |
| | Set and Not Null | Set But Null | Unset |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word} | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word | assign word |
| ${parameter=word} | substitute parameter | substitute null | assign word |
| ${parameter:?word} | substitute parameter | error, exit | error, exit |
| ${parameter?word} | substitute parameter | substitute null | error, exit |
| ${parameter:+word} | substitute word | substitute null | substitute null |
| ${parameter+word} | substitute word | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
来源:POSIX:参数扩展:
在使用"替换"显示的所有情况下,表达式将替换为显示的值.在使用"assign"显示的所有情况下,都会为参数分配该值,该值也会替换表达式.
小智 225
虽然这里陈述的大部分技术都是正确的,但是bash 4.2支持对变量(man bash)的存在进行实际测试,而不是测试变量的值.
[[ -v foo ]]; echo $?
# 1
foo=bar
[[ -v foo ]]; echo $?
# 0
foo=""
[[ -v foo ]]; echo $?
# 0
Run Code Online (Sandbox Code Playgroud)
值得注意的是,这种方法在用于检查set -u/ set -o nounsetmode中的未设置变量时不会导致错误,这与许多其他方法(例如使用)不同[ -z.
enn*_*ler 175
有很多方法可以做到这一点,其中之一是:
if [ -z "$1" ]
Run Code Online (Sandbox Code Playgroud)
如果$ 1为null或未设置,则成功
dei*_*zel 66
我总是发现另一个答案中的POSIX表很慢,所以这是我对它的看法:
+----------------------+------------+-----------------------+-----------------------+
| if VARIABLE is: | set | empty | unset |
+----------------------+------------+-----------------------+-----------------------+
- | ${VARIABLE-default} | $VARIABLE | "" | "default" |
= | ${VARIABLE=default} | $VARIABLE | "" | $(VARIABLE="default") |
? | ${VARIABLE?default} | $VARIABLE | "" | exit 127 |
+ | ${VARIABLE+default} | "default" | "default" | "" |
+----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE | "default" | "default" |
:= | ${VARIABLE:=default} | $VARIABLE | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE | exit 127 | exit 127 |
:+ | ${VARIABLE:+default} | "default" | "" | "" |
+----------------------+------------+-----------------------+-----------------------+
Run Code Online (Sandbox Code Playgroud)
请注意,每个组(有和没有前置冒号)具有相同的set和unset情况,因此唯一不同的是如何处理空案例.
对于前面的冒号,空和未设置的情况是相同的,所以我会尽可能使用那些(即使用:=,不仅仅是=因为空的情况不一致).
标题:
VARIABLE是非空的(VARIABLE="something")VARIABLE是空/ null(VARIABLE="")VARIABLE不存在(unset VARIABLE)价值观:
$VARIABLE 表示结果是变量的原始值."default" 表示结果是提供的替换字符串."" 表示结果为null(空字符串).exit 127 表示脚本停止执行退出代码127.$(VARIABLE="default")表示结果是变量的原始值,并且提供的替换字符串将分配给变量以供将来使用.小智 64
为了查看变量是否为非空,我使用
if [[ $var ]]; then ... # `$var' expands to a nonempty string
Run Code Online (Sandbox Code Playgroud)
如果变量未设置或为空,则相反测试:
if [[ ! $var ]]; then ... # `$var' expands to the empty string (set or not)
Run Code Online (Sandbox Code Playgroud)
要查看是否设置了变量(空或非空),我使用
if [[ ${var+x} ]]; then ... # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ... # Parameter 1 exists (empty or nonempty)
Run Code Online (Sandbox Code Playgroud)
相反的测试是否未设置变量:
if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ... # We were called with no arguments
Run Code Online (Sandbox Code Playgroud)
Sea*_*nor 33
在Bash的现代版本(我认为4.2或更高版本;我不确定),我会尝试这样做:
if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
echo "Variable is unset"
elif [ -z "$SOMEVARIABLE" ]
then
echo "Variable is set to an empty string"
else
echo "Variable is set to some string"
fi
Run Code Online (Sandbox Code Playgroud)
Pau*_*sey 21
if [ "$1" != "" ]; then
echo \$1 is set
else
echo \$1 is not set
fi
Run Code Online (Sandbox Code Playgroud)
虽然对于参数,我认为通常最好测试$#,即参数的数量.
if [ $# -gt 0 ]; then
echo \$1 is set
else
echo \$1 is not set
fi
Run Code Online (Sandbox Code Playgroud)
ece*_*ulm 18
对于那些希望在脚本中 检查未设置或空的人set -u:
if [ -z "${var-}" ]; then
echo "Must provide var environment variable. Exiting...."
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
如果未设置[ -z "$var" ]失败,常规检查将失败,var; unbound variable如果set -u但[ -z "${var-}" ] 扩展为空字符串var.
Sho*_*dan 17
如果你像我一样,你正在寻找的实际上是
“bash 仅在设置变量时运行命令”
你希望将其作为一句台词,所以下面这行就是你想要的
仅适用于 Bash 4.2 或更高版本
if [[ -v mytest ]]; then echo "this runs only if variable is set"; fi
Run Code Online (Sandbox Code Playgroud)
if [[ ! -v mytest2 ]]; then echo "this runs only if variable is not set"; fi
Run Code Online (Sandbox Code Playgroud)
Jar*_*ney 16
这对我有用.如果未设置参数,我希望我的脚本退出并显示错误消息.
#!/usr/bin/env bash
set -o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Run Code Online (Sandbox Code Playgroud)
运行时返回错误
peek@peek:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument
Run Code Online (Sandbox Code Playgroud)
如果您只想检查值set = VALID或unset/empty = INVALID,请尝试此选项.
TSET="good val"
TEMPTY=""
unset TUNSET
if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
Run Code Online (Sandbox Code Playgroud)
或者,即使是短暂的测试;-)
[ "${TSET:-}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"
Run Code Online (Sandbox Code Playgroud)
这就是问题的答案.如果您只想检查值set/empty = VALID或unset = INVALID,请使用此选项.
注意,"..- 1}"中的"1"是无关紧要的,它可以是任何东西(如x)
TSET="good val"
TEMPTY=""
unset TUNSET
if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
Run Code Online (Sandbox Code Playgroud)
简短的测试
[ "${TSET+1}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"
Run Code Online (Sandbox Code Playgroud)
我把这个答案献给了@ mklement0(评论),他们挑战我准确地回答这个问题.
参考http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
che*_*ner 14
阅读bash手册页的"参数扩展"部分.参数扩展不为要设置的变量提供常规测试,但如果未设置参数,则可以对参数执行多项操作.
例如:
function a {
first_arg=${1-foo}
# rest of the function
}
Run Code Online (Sandbox Code Playgroud)
将设置为first_arg等于$1是否已分配,否则使用值"foo".如果a绝对必须采用单个参数,并且不存在良好的默认值,则可以在未给出参数时退出并显示错误消息:
function a {
: ${1?a must take a single argument}
# rest of the function
}
Run Code Online (Sandbox Code Playgroud)
(注意使用:as作为一个null命令,它只是扩展了它的参数值.$1在这个例子中我们不想做任何事情,如果没有设置就退出)
Mar*_*amp 14
由于bash标签的缘故,我给出了一个以Bash为重点的答案。
只要您仅在Bash中处理命名变量,此函数就应始终告诉您变量是否已设置,即使它是一个空数组也是如此。
is-variable-set() {
declare -p $1 &>dev/null
}
Run Code Online (Sandbox Code Playgroud)
在Bash中(至少可以追溯到3.0),如果var是声明的/设置的变量,则declare -p var输出declare命令,将变量设置var为当前类型和值,并返回状态代码0(成功)。如果var未声明,则declare -p var输出一条错误消息stderr并返回状态码1。使用&>/dev/null,将常规stdout和stderr输出重定向到/dev/null,从不被看到,并且不更改状态码。因此,该函数仅返回状态码。
[ -n "$var" ]:仅检查是否${var[0]}为非空。(在Bash中,$var与相同${var[0]}。)[ -n "${var+x}" ]:仅检查是否${var[0]}已设置。[ "${#var[@]}" != 0 ]:仅检查是否设置了至少一个索引$var。
这仅适用于命名的变量(包括$_),而不是某些特殊变量($!,$@,$#,$$,$*,$?,$-,$0,$1,$2,...,和任何我可能已经忘记了)。由于这些都不是数组,因此POSIX样式[ -n "${var+x}" ]适用于所有这些特殊变量。但是要当心将其包装在函数中,因为调用函数时许多特殊变量会更改值/存在性。
如果您的脚本具有数组,并且您正尝试使其与尽可能多的Shell兼容,则可以考虑使用typeset -p而不是declare -p。我读过ksh仅支持前者,但无法对其进行测试。我确实知道Bash 3.0+和Zsh 5.5.1都支持typeset -p和declare -p,不同之处仅在于其中一个可以替代另一个。但是我没有测试过这两个关键字以外的差异,也没有测试过其他shell。
如果需要脚本与POSIX sh兼容,则不能使用数组。没有数组,[ -n "{$var+x}" ]工作。
此功能取消设置变量var,evalS中的传递代码,运行测试,以确定是否var由设定evald代码,最后示出了用于不同的测试所得到的状态代码。
我跳过了test -v var,[ -v var ]并且[[ -v var ]]因为它们产生与POSIX标准相同的结果[ -n "${var+x}" ],同时需要Bash 4.2+。我也跳过了,typeset -p因为它与declare -p我测试过的shell 相同(Bash 3.0到5.0,以及Zsh 5.5.1)。
is-var-set-after() {
# Set var by passed expression.
unset var
eval "$1"
# Run the tests, in increasing order of accuracy.
[ -n "$var" ] # (index 0 of) var is nonempty
nonempty=$?
[ -n "${var+x}" ] # (index 0 of) var is set, maybe empty
plus=$?
[ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty
count=$?
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
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果未将变量声明为关联数组,则Bash将非数字数组索引视为“ 0”,则测试结果可能是意外的。而且,关联数组仅在Bash 4.0+中有效。
# 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 0
is-var-set-after "var=(foo)" # 0 0 0 0
is-var-set-after "var=([0]=foo)" # 0 0 0 0
is-var-set-after "var=([x]=foo)" # 0 0 0 0
is-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 0
is-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 0
is-var-set-after "var=([1]=foo)" # 1 1 0 0
is-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 0
is-var-set-after "declare -a var" # 1 1 1 0
is-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
Run Code Online (Sandbox Code Playgroud)
该测试在助记符标题行对应于[ -n "$var" ],[ -n "${var+x}" ],[ "${#var[@]}" != 0 ],和declare -p var,分别。
test: -n +x #@ -p
var=foo: 0 0 0 0
var=(foo): 0 0 0 0
var=([0]=foo): 0 0 0 0
var=([x]=foo): 0 0 0 0
var=([y]=bar [x]=foo): 0 0 0 0
var='': 1 0 0 0
var=([0]=''): 1 0 0 0
var=([1]=''): 1 1 0 0
var=([1]=foo): 1 1 0 0
declare -A var; var=([x]=foo): 1 1 0 0
var=(): 1 1 1 0
declare -a var: 1 1 1 0
declare -A var: 1 1 1 0
unset var: 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
declare -p var &>/dev/null(至少100%?)至少从3.0开始就可用于测试Bash中的命名变量。[ -n "${var+x}" ]在符合POSIX的情况下是可靠的,但不能处理数组。- 还存在其他测试,用于检查变量是否为非空,以及检查其他外壳程序中已声明的变量。但是这些测试都不适合Bash和POSIX脚本。
Ale*_*oVD 13
在bash中你可以-v在[[ ]]内置中使用:
#! /bin/bash -u
if [[ ! -v SOMEVAR ]]; then
SOMEVAR='hello'
fi
echo $SOMEVAR
Run Code Online (Sandbox Code Playgroud)
Jea*_*vin 12
要测试变量是否var已设置:[ ${var+x} ].
要测试变量是否按名称设置:[ ${!name+x} ]。
要测试是否设置了位置参数:[ ${N+x} ],其中 N 实际上是一个整数。
这个答案几乎与 Lionel\xe2\x80\x99s 类似,但通过省略来探索更简约的方式-z.
要测试是否设置了命名变量:
\nfunction is_set {\n local v=$1\n echo -n "${v}"\n if [ ${!v+x} ]; then\n echo " = \'${!v}\'"\n else\n echo " is unset"\n fi\n}\nRun Code Online (Sandbox Code Playgroud)\n要测试是否设置了位置参数:
\nfunction a {\n if [ ${1+x} ]; then\n local arg=$1\n echo "a \'${arg}\'"\n else\n echo "a: arg is unset"\n fi\n}\nRun Code Online (Sandbox Code Playgroud)\n测试表明不需要额外注意空格和有效的测试表达式。
\nset -eu\n\nV1=a\nV2=\nV4=-gt\nV5="1 -gt 2"\nV6="! -z 1"\nV7=\'$(exit 1)\'\n\nis_set V1\nis_set V2\nis_set V3\nis_set V4\nis_set V5\nis_set V6\nis_set V7\n\na 1\na\na "1 -gt 2"\na 1 -gt 2\nRun Code Online (Sandbox Code Playgroud)\n$ ./test.sh\n\nV1 = \'a\'\nV2 = \'\'\nV3 is unset\nV4 = \'-gt\'\nV5 = \'1 -gt 2\'\nV6 = \'! -z 1\'\nV7 = \'$(exit 1)\'\na \'1\'\na: arg is unset\na \'1 -gt 2\'\na \'1\'\nRun Code Online (Sandbox Code Playgroud)\n最后,请注意它set -eu可以保护我们免受常见错误的影响,例如变量名称中的拼写错误。我建议使用它,但这意味着未设置的变量和设置为空字符串的变量之间的差异得到了正确处理。
inf*_*ler 11
使用test -n "${var-}"以检查变量不为空(并因此必须定义/设置得)。用法:
if test -n "${name-}"; then
echo "name is set to $name"
else
echo "name is not set or empty"
fi
Run Code Online (Sandbox Code Playgroud)
使用test ! -z "${var+}"以检查变量定义/套(即使是空的)。用法:
if test ! -z "${var+}"; then
echo "name is set to $name"
else
echo "name is not set"
fi
Run Code Online (Sandbox Code Playgroud)
请注意,第一个用例在 shell 脚本中更为常见,这也是您通常想要使用的。
要了解此解决方案的工作原理,您需要了解POSIXtest命令和 POSIX shell 参数扩展 ( spec ),因此让我们介绍了解答案所需的绝对基础知识。
test 命令评估表达式并返回 true 或 false(通过其退出状态)。-n如果操作数是非空字符串,则运算符返回 true。例如,test -n "a"返回true,而test -n ""返回false。现在,要检查变量是否为空(这意味着它必须被定义),您可以使用test -n "$var". 但是,一些 shell 脚本有一个选项 set ( set -u),它会导致对未定义变量的任何引用发出错误,因此如果未定义变量var,则表达式$a将导致错误。要正确处理这种情况,您必须使用变量扩展,如果变量未定义,它将告诉 shell 用替代字符串替换变量,避免上述错误。
变量扩展${var-}意味着:如果变量var未定义(也称为“未设置”),则将其替换为空字符串。因此,test -n "${var-}"如果$var不为空,则返回 true ,这几乎总是您要在 shell 脚本中检查的内容。反向检查,如果$var未定义或不为空,则为test -z "${var-}".
现在到第二个用例:检查变量var是否已定义,是否为空。这是一个不太常见的用例,稍微复杂一些,我建议您阅读Lionels 的精彩答案以更好地理解它。
为了清楚地回答 OP 关于如何确定是否设置变量的问题,@Lionel 的回答是正确的:
if test "${name+x}"; then
echo 'name is set'
else
echo 'name is not set'
fi
Run Code Online (Sandbox Code Playgroud)
这个问题已经有很多答案,但没有一个提供真正的布尔表达式来清楚地区分变量值。
以下是我想出的一些明确的表达方式:
+-----------------------+-------------+---------+------------+
| 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 |
+-----------------------+-------------+---------+------------+
Run Code Online (Sandbox Code Playgroud)
顺便说一下,这些表达式是等价的:
test <expression><=>[ <expression> ]
其他需要谨慎使用的歧义表达:
+----------------------+-------------+---------+------------+
| Expression in script | name='fish' | name='' | unset name |
+----------------------+-------------+---------+------------+
| test "${name+x}" | TRUE | TRUE | f |
| test "${name-x}" | TRUE | f | TRUE |
| test -z "$name" | f | TRUE | TRUE |
| test ! "$name" | f | TRUE | TRUE |
| test ! -n "$name" | f | TRUE | TRUE |
| test "$name" = '' | f | TRUE | TRUE |
+----------------------+-------------+---------+------------+
Run Code Online (Sandbox Code Playgroud)
使用[[ -z "$var" ]]是了解是否设置了变量的最简单方法,但是该选项-z无法区分未设置的变量和设置为空字符串的变量:
$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset"
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset
Run Code Online (Sandbox Code Playgroud)
最好根据变量的类型进行检查:env变量,参数或常规变量。
对于环境变量:
[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"
Run Code Online (Sandbox Code Playgroud)
对于参数(例如,检查parameter的存在$5):
[[ $# -ge 5 ]] && echo "Set" || echo "Unset"
Run Code Online (Sandbox Code Playgroud)
对于常规变量(使用辅助函数,以一种简洁的方式进行操作):
function declare_var {
declare -p "$1" &> /dev/null
}
declare_var "var_name" && echo "Set" || echo "Unset"
Run Code Online (Sandbox Code Playgroud)
笔记:
$#:为您提供位置参数的数量。declare -p:为您提供作为参数传递的变量的定义。如果存在,则返回0,否则返回1,并显示错误消息。&> /dev/null:抑制输出declare -p而不影响其返回码。
你可以做:
function a {
if [ ! -z "$1" ]; then
echo '$1 is set'
fi
}
Run Code Online (Sandbox Code Playgroud)
set -u启用“重击”选项时,以上答案无效。另外,它们不是动态的,例如,如何测试定义了名称为“ dummy”的变量?尝试这个:
is_var_defined()
{
if [ $# -ne 1 ]
then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1
fi
# 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.
}
Run Code Online (Sandbox Code Playgroud)
相关:在Bash中,如何测试是否在“ -u”模式下定义了变量
我很惊讶没有人试图编写一个 shell 脚本来以编程方式生成臭名昭著的难以理解的 table。既然我们在这里学习编码技术,为什么不用代码表达答案呢?:) 这是我的看法(应该适用于任何 POSIX shell):
H="+-%s-+-%s----+-%s----+-%s--+\n" # table divider printf format
R="| %-10s | %-10s | %-10s | %-10s |\n" # table row printf format
S='V' # S is a variable that is set-and-not-null
N='' # 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 U
printf "$R" "\${FOO-x} " "${S-x} " "${N-x} " "${U-x} "; S='V';N='';unset U
printf "$R" "\${FOO:=x}" "${S:=x}" "${N:=x}" "${U:=x} "; S='V';N='';unset U
printf "$R" "\${FOO=x} " "${S=x} " "${N=x} " "${U=x} "; S='V';N='';unset U
printf "$R" "\${FOO:?x}" "${S:?x}" "<error>" "<error> "; S='V';N='';unset U
printf "$R" "\${FOO?x} " "${S?x} " "${N?x} " "<error> "; S='V';N='';unset U
printf "$R" "\${FOO:+x}" "${S:+x}" "${N:+x}" "${U:+x} "; S='V';N='';unset U
printf "$R" "\${FOO+x} " "${S+x} " "${N+x} " "${U+x} "; S='V';N='';unset U
printf "$H" "----------" "-------" "-------" "---------";
# For reference, the following two lines are the literal rows of the table
# which would cause the script to exit and so have had <error> written in.
#printf "$R" "\${FOO:?x}" "${S:?x}" "${N:?x}" "${U:?x} "; S='V';N='';unset U
#printf "$R" "\${FOO?x} " "${S?x} " "${N?x} " "${U?x} "; S='V';N='';unset U
Run Code Online (Sandbox Code Playgroud)
以及运行脚本的输出:
+------------+------------+------------+------------+
| 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 | |
+------------+------------+------------+------------+
Run Code Online (Sandbox Code Playgroud)
该脚本缺少一些功能,例如在副作用分配发生(或不发生)发生时显示,但也许其他一些更有野心的人想要从这个起点开始运行。
| 归档时间: |
|
| 查看次数: |
1191482 次 |
| 最近记录: |