我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否向函数提供了第一个参数?
function a {
# if $1 is set ?
}
我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否向函数提供了第一个参数?
function a {
# if $1 is set ?
}
当前回答
要查看变量是否为非空,我使用
if [[ $var ]]; then ... # `$var' expands to a nonempty string
如果变量未设置或为空,则相反:
if [[ ! $var ]]; then ... # `$var' expands to the empty string (set or not)
要查看变量是否已设置(空或非空),我使用
if [[ ${var+x} ]]; then ... # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ... # Parameter 1 exists (empty or nonempty)
如果变量未设置,则进行相反的测试:
if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ... # We were called with no arguments
其他回答
我的首选方式是:
$ var=10
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
因此,基本上,如果一个变量被设置,它就变成了“对结果false的否定”(true=“被设置”)。
并且,如果它未设置,它将变成“对结果true的否定”(因为空结果的求值结果为true)(因此将以false=“NOT set”结束)。
(通常)正确的方式
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
其中${var+x}是一个参数扩展,如果var未设置,则其求值结果为空,否则替换字符串x。
报价摘要
可以省略引号(所以我们可以说${var+x}而不是“${var+x}”),因为这种语法和用法保证它只扩展到不需要引号的对象(因为它要么扩展到x(不包含换行符,因此不需要引号),要么不扩展到任何对象(这导致[-z],它方便地计算出与[-z“”]相同的值(true))。
然而,虽然可以安全地省略引号,而且这并不是所有人都能立即看到的(这对第一位也是主要Bash编码者的引号解释作者来说都不明显),但有时最好使用引号[-z“${var+x}”]来编写解决方案,代价很小,可能会导致O(1)速度损失。第一作者还将此添加为使用此解决方案的代码旁边的注释,给出了此答案的URL,现在还包括了为什么可以安全地省略引号的解释。
(经常)错误的方式
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
这通常是错误的,因为它无法区分未设置的变量和设置为空字符串的变量。也就是说,如果var='',则上述解决方案将输出“var为空”。
在用户必须指定扩展名或其他财产列表的情况下,必须区分unset和“设置为空字符串”,如果不指定,则默认为非空值,而指定空字符串应使脚本使用空扩展名或附加财产列表。
然而,这种区别在每种情况下可能都不是必不可少的。在这种情况下,[-z“$var”]就可以了。
为了明确回答OP关于如何确定变量是否已设置的问题,Lionel的回答是正确的:
if test "${name+x}"; then
echo 'name is set'
else
echo '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 |
+-----------------------+-------------+---------+------------+
顺便说一下,这些表达式是等价的:测试<表达式><=>〔<表达式>〕
其他需谨慎使用的歧义表达:
+----------------------+-------------+---------+------------+
| 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 |
+----------------------+-------------+---------+------------+
如果你和我一样,你所寻找的其实是
“如果设置了变量,bash仅运行命令”
你希望这是一行,所以下面这行是你想要的
仅适用于Bash 4.2或更高版本
仅在设置时运行
if [[ -v mytest ]]; then echo "this runs only if variable is set"; fi
仅在未设置时运行
if [[ ! -v mytest2 ]]; then echo "this runs only if variable is not set"; fi
阅读bash手册页的“参数扩展”部分。参数扩展并不能为正在设置的变量提供常规测试,但如果未设置参数,可以对其执行一些操作。
例如:
function a {
first_arg=${1-foo}
# rest of the function
}
如果分配了firstarg,则将其设置为等于$1,否则将使用值“foo”。如果绝对必须采用单个参数,并且不存在良好的默认值,则可以在未给定参数时退出并显示错误消息:
function a {
: ${1?a must take a single argument}
# rest of the function
}
(注意:作为null命令的用法,它只是扩展其参数的值。在本例中,我们不想对$1做任何操作,如果未设置,只需退出)