我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否将第一个参数赋予函数?
function a {
# if $1 is set ?
}
-v
测试也是正确的,尽管这似乎仅适用于新版本的,bash
并且不能跨外壳移植。
我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否将第一个参数赋予函数?
function a {
# if $1 is set ?
}
-v
测试也是正确的,尽管这似乎仅适用于新版本的,bash
并且不能跨外壳移植。
Answers:
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 ]
,可以方便地求出相同的值(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
这通常是错误的,因为它无法区分未设置的变量和设置为空字符串的变量。也就是说,如果var=''
,则上述解决方案将输出“ var is blank”。
在用户必须指定扩展名或其他属性列表且未指定属性默认情况下默认为非空值的情况下,未设置和“设置为空字符串”之间的区别至关重要。使脚本使用空扩展名或其他属性列表。
但是,这种区分可能并非在每种情况下都必不可少。在那种情况下 [ -z "$var" ]
就可以了。
${var+x}
是可以使用的正确替代方法。使用所[ -z ${var:+x} ]
产生的结果与相同[ -z "$var" ]
。
[ -z "" -a -z ${var+x} ]
,bash: [: argument expected
在bash 4.3-ubuntu中获取(但在zsh中则不需要),则看起来引号是必需的。我真的不喜欢使用在某些情况下可以使用的语法的答案。
[ -z $var ]
不比省略引号更“错误”。无论哪种方式,您都在对输入进行假设。如果您可以将空字符串视为未设置,则只[ -z $var ]
需要一个。
要检查非空/非零字符串变量,即是否已设置,请使用
if [ -n "$1" ]
与的相反-z
。我发现自己使用的-n
次数超过-z
。
您将使用它像:
if [ -n "$1" ]; then
echo "You supplied the first parameter!"
else
echo "First parameter not supplied."
fi
[]
尤其适用于shell(非bash)脚本。
set -u
。
这是测试参数是否为unset,为空(“ Null”)或设置为值的方法:
+--------------------+----------------------+-----------------+-----------------+
| Expression | parameter | parameter | parameter |
| in script: | 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 |
+--------------------+----------------------+-----------------+-----------------+
来源:POSIX:参数扩展:
在所有显示为“替换”的情况下,表达式都将替换为显示的值。在所有显示为“ assign”的情况下,都会为参数分配该值,该值也会替换表达式。
为了展示这一点:
+--------------------+----------------------+-----------------+-----------------+
| Expression | FOO="world" | FOO="" | unset FOO |
| in script: | (Set and Not Null) | (Set But Null) | (Unset) |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello} | world | hello | hello |
| ${FOO-hello} | world | "" | hello |
| ${FOO:=hello} | world | FOO=hello | FOO=hello |
| ${FOO=hello} | world | "" | FOO=hello |
| ${FOO:?hello} | world | error, exit | error, exit |
| ${FOO?hello} | world | "" | error, exit |
| ${FOO:+hello} | hello | "" | "" |
| ${FOO+hello} | hello | hello | "" |
+--------------------+----------------------+-----------------+-----------------+
set foo; echo ${1:-set but null or unset}
“ foo”; set --; echo ${1:-set but null or unset}
回声设置但为空...
set
:-)
: ${FOOBAR:=/etc/foobar.conf}
为变量设置默认值(如果未设置或为null)。
parameter
是任何变量名称。 word
是根据要使用的表中的语法以及变量$parameter
是设置,设置为null还是未设置来替换的字符串。不是使事情变得更复杂,而是word
还可以包含变量!这对于传递以字符分隔的可选参数非常有用。例如: 如果设置${parameter:+,${parameter}}
了逗号,,$parameter
但输出一个逗号分隔但不为null。在这种情况下,word
是,${parameter}
虽然此处介绍的大多数技术都是正确的,但bash 4.2支持对变量(man bash)的存在进行实际测试,而不是测试变量的值。
[[ -v foo ]]; echo $?
# 1
foo=bar
[[ -v foo ]]; echo $?
# 0
foo=""
[[ -v foo ]]; echo $?
# 0
值得注意的是,与许多其他方法(例如使用)不同,该方法在set -u
/ set -o nounset
模式下检查未设置的变量时不会导致错误[ -z
。
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
执行此操作的方法有很多种,其中之一是:
if [ -z "$1" ]
如果$ 1为null或未设置,则此操作成功
[[ ]]
只是可移植性陷阱。if [ -n "$1" ]
应该在这里使用。
foo=""
,$foo
具有一个值,但-z
只会报告其为空。而-z $foo
将炸毁,如果你有set -o nounset
。
我总是在另一个答案中发现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" | "" | "" |
+----------------------+------------+-----------------------+-----------------------+
请注意,每个组(有或没有前冒号)都具有相同的设置和未设置案例,因此唯一不同的是如何处理空案例。
对于前面的冒号,空和未设置的情况是相同的,因此我将在可能的情况下使用它们(即,使用:=
,而不仅仅是=
,因为空情况不一致)。
标题:
VARIABLE
非空(VARIABLE="something"
)VARIABLE
为空/空(VARIABLE=""
)VARIABLE
不存在(unset VARIABLE
)值:
$VARIABLE
表示结果是变量的原始值。"default"
表示结果是提供的替换字符串。""
表示结果为空(空字符串)。exit 127
表示脚本停止执行,退出代码为127。$(VARIABLE="default")
里指的是该变量的初始值和提供被分配给将来使用该变量的替换字符串。VARIABLE=""
可以写成VARIABLE=
。尽管如此,前者更具可读性。
要查看变量是否为非空,我使用
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
${variable+x}
可读性较差(且显而易见)
在现代版本的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
[ -v "$VARNAME" ]
不是不正确的,而只是执行不同的测试。假设VARNAME=foo
; 然后检查是否foo
设置了名为的变量。
-v
内容不符合POSIX
[: -v: unexpected operator
,则必须确保使用bash
而不是sh
。
if [ "$1" != "" ]; then
echo \$1 is set
else
echo \$1 is not set
fi
虽然对于参数,通常我认为最好测试$#,这是参数的数量。
if [ $# -gt 0 ]; then
echo \$1 is set
else
echo \$1 is not set
fi
[ "$1" != "" ]
(或[ -n "$1" ]
)...
$1
其设置为空字符串,则将失败。
$1
设置为空字符串时不起作用。
set -o nounset
打开,它将失败。
由于bash
标签的缘故,我给出了一个以Bash为重点的答案。
只要您仅在Bash中处理命名变量,此函数就应该始终告诉您变量是否已设置,即使它是一个空数组。
variable-is-set() {
declare -p "$1" &>/dev/null
}
在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
,eval
S中的传递代码,运行测试,以确定是否var
由设定eval
d代码,最后示出了用于不同的测试所得到的状态代码。
我跳过了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
}
请注意,如果未将变量声明为关联数组,则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
该测试在助记符标题行对应于[ -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
declare -p var &>/dev/null
(至少100%?)至少从3.0开始就可以可靠地测试Bash中的命名变量。[ -n "${var+x}" ]
在符合POSIX的情况下是可靠的,但不能处理数组。- 还存在其他测试,用于检查变量是否为非空,以及检查其他外壳程序中已声明的变量。但是这些测试都不适合Bash和POSIX脚本。
declare -p var &>/dev/null
)是唯一有效的答案。谢谢!
... &> /dev/null
但这样我就不允许我进行单个字符编辑🙄(必须大于6个字符-甚至尝试添加空格但没有用)。另外,可能值得更改该函数以切换到$1
名为变量的示例(例如OUTPUT_DIR
),因为如您所指出的,特殊变量(如)$1
在这里不起作用。无论如何,这是一项重要的编辑,否则代码将寻找在名为null
的相对目录中创建一个名为的文件dev
。顺便说一句-好答案!
declare -p PATH &> /dev/null
返回0,其中declare -p ASDFASDGFASKDF &> /dev/null
返回1。(在bash 5.0.11(1)-release上)
declare var
声明VAR变量,但它并没有将其设置在以下方面set -o nounset
:测试declare foo bar=; set -o nounset; echo $bar; echo $foo
/
!我已解决此问题,但我认为逻辑很混乱,无法保证功能,尤其是考虑到@xebeche的评论。@xebeche这对我的回答很不方便。。。看来我必须尝试类似declare -p "$1" | grep =
或的方法test -v "$1"
。
对于那些希望在脚本中使用 以下命令检查未设置或为空的对象set -u
:
if [ -z "${var-}" ]; then
echo "Must provide var environment variable. Exiting...."
exit 1
fi
常规[ -z "$var" ]
检查将以var; unbound variable
if 失败,set -u
但如果未设置而未失败则[ -z "${var-}" ]
扩展为空字符串var
。
${var:-}
,不是${var-}
。但是在Bash中,我可以确认即使没有冒号,它也能正常工作。
${var:-}
并${var-}
意味着不同的事情。${var:-}
将扩大仿佛空字符串var
未设置或为空并且${var-}
将扩大到仅如果取消设置空字符串。
这对我有用。如果未设置参数,我希望脚本退出并显示错误消息。
#!/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}"
运行时返回错误
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 / 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
或者,即使是简短测试;-)
[ "${TSET:-}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"
这就是问题的答案。如果只想检查值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
简短测试
[ "${TSET+1}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"
我将这个答案献给@ mklement0(评论),他要求我准确回答这个问题。
参考http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
要检查变量是否设置为非空值,请使用[ -n "$x" ]
,如其他变量所示。
在大多数情况下,以与未设置的变量相同的方式对待具有空值的变量是一个好主意。但是你可以区分这两种,如果你需要:[ -n "${x+set}" ]
("${x+set}"
膨胀到set
如果x
如果被设置,为空字符串x
未设置)。
要检查是否已传递参数,请测试$#
一下,它是传递给函数(或不在函数中时传递给脚本)的参数数量(请参阅Paul的答案)。
阅读bash
手册页的“参数扩展”部分。参数扩展不能为设置的变量提供一般测试,但是如果没有设置参数,您可以对它做几件事。
例如:
function a {
first_arg=${1-foo}
# rest of the function
}
将被设置为first_arg
等于$1
是否已分配,否则将使用值“ foo”。如果a
绝对必须使用一个参数,并且没有良好的默认值,则在不指定参数的情况下可以退出并显示错误消息:
function a {
: ${1?a must take a single argument}
# rest of the function
}
(请注意,使用:
as作为空命令只会扩展其参数的值。$1
在此示例中,我们不想执行任何操作,如果未设置,则退出)
: ${var?message}
。
在bash中,您可以-v
在[[ ]]
内置函数中使用:
#! /bin/bash -u
if [[ ! -v SOMEVAR ]]; then
SOMEVAR='hello'
fi
echo $SOMEVAR
使用[[ -z "$var" ]]
是了解是否设置了变量的最简单方法,但是该选项-z
无法区分未设置的变量和设置为空字符串的变量:
$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset"
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset
最好根据变量的类型进行检查:env变量,参数或常规变量。
对于环境变量:
[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"
对于参数(例如,检查parameter的存在$5
):
[[ $# -ge 5 ]] && echo "Set" || echo "Unset"
对于常规变量(使用辅助函数,以一种简洁的方式进行操作):
function declare_var {
declare -p "$1" &> /dev/null
}
declare_var "var_name" && echo "Set" || echo "Unset"
笔记:
$#
:为您提供位置参数的数量。declare -p
:为您提供作为参数传递的变量的定义。如果存在,则返回0,否则返回1,并显示错误消息。&> /dev/null
:抑制输出declare -p
而不影响其返回码。
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.
}
你可以做:
function a {
if [ ! -z "$1" ]; then
echo '$1 is set'
fi
}
-n
而不是否定-z
。
$1
,即[ ! -z "$1" ]
。或者您可以用[[ ! -z $1 ]]
bash / ksh / zsh 编写。
$1
其设置为空字符串,则将失败。
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi
if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
这是我每天使用的:
#
# Check if a variable is set
# param1 name of the variable
#
function is_set()
{
[[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}
在Linux和Solaris(低至bash 3.0)下,此方法效果很好。
bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1
我喜欢辅助功能来隐藏bash的原始细节。在这种情况下,这样做会增加更多(隐藏的)粗度:
# 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} ]
}
因为我最初在此实现中遇到错误(受到Jens和Lionel的回答启发),所以我想出了一个不同的解决方案:
# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
declare -p $1 &>/dev/null
}
我发现它更简单,更轻松,更易于理解/记住。测试用例表明它是等效的:
function main()
{
declare -i xyz
local foo
local bar=
local baz=''
IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"
IsDeclared xyz; echo "IsDeclared xyz: $?"
IsDeclared foo; echo "IsDeclared foo: $?"
IsDeclared bar; echo "IsDeclared bar: $?"
IsDeclared baz; echo "IsDeclared baz: $?"
}
main
测试用例还表明,local var
不NOT声明VAR(除非后跟“=”)。在相当长的一段时间里,我以为我以这种方式声明了变量,只是发现现在我只是表达了自己的意图...我猜这是一个禁忌。
IsDeclared_Tricky xyz:1
IsDeclared_Tricky foo:1
IsDeclared_Tricky条:0
IsDeclared_Tricky baz:0
IsDeclared xyz:1
IsDeclared foo:1
IsDeclared bar:0
IsDeclared baz:0
奖励:用例
我主要使用此测试以某种 “优雅”且安全的方式(几乎类似于接口...)为函数提供(并返回)参数:
#auxiliary functions
function die()
{
echo "Error: $1"; exit 1
}
function assertVariableDeclared()
{
IsDeclared "$1" || die "variable not declared: $1"
}
function expectVariables()
{
while (( $# > 0 )); do
assertVariableDeclared $1; shift
done
}
# actual example
function exampleFunction()
{
expectVariables inputStr outputStr
outputStr="$inputStr world!"
}
function bonus()
{
local inputStr='Hello'
local outputStr= # remove this to trigger error
exampleFunction
echo $outputStr
}
bonus
如果全部调用都需要声明变量:
你好,世界!
其他:
错误:未声明变量:outputStr
略过所有答案后,这也有效:
if [[ -z $SOME_VAR ]]; then read -p "Enter a value for SOME_VAR: " SOME_VAR; fi
echo "SOME_VAR=$SOME_VAR"
如果您没有放置SOME_VAR
我所拥有的东西$SOME_VAR
,它将设置为空值;$
这项工作是必要的。
set -u
的效果,它将打印unboud variable
错误
我总是使用这一代码,是基于这样的事实,即任何首次看到该代码的人都容易理解:
if [ "$variable" = "" ]
then
echo "Variable X is empty"
fi
并且,如果要检查是否不为空;
if [ ! "$variable" = "" ]
then
echo "Variable X is not empty"
fi
而已。
[[ ... ]]
而不是[ ... ]
。后者实际上是一个外部命令,对于是否设置了变量没有任何可见性。
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
。