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
12
启用Bash选项 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.
}
#!/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
#! /bin/bash -u
if [[ ! -v SOMEVAR ]]; then
SOMEVAR='hello'
fi
echo $SOMEVAR
0
我最喜欢的方式是:
$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
is-var-set () {
results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}"
if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then
echo -e "$1: var's unset.\t$results"
elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then
echo -e "$1: var is set. \t$results"
else
echo -e "$1: Is var set? \t$results"
fi
unset var # so we don't have to do it everywhere else
}
unset var; is-var-set 1 # var unset
var=''; is-var-set 2 # var[0] set to ''
var=foo; is-var-set 3 # var[0] set to 'foo'
var=(); is-var-set 4 # var unset (all indices)
var=(foo); is-var-set 5 # var[0] set to 'foo'
var=([0]=foo); is-var-set 6 # var[0] set to 'foo'
var=([1]=foo); is-var-set 7 # var[0] unset, but var[1] set to 'foo'
declare -a var; is-var-set 8 # var empty, but declared as an array
declare -A var; is-var-set 9 # var empty, but declared as an associative array
declare -A var # Because is-var-set() conveniently unsets it
var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var's otherwise empty
declare -a var # Demonstrate that Bash knows about var, even when there's
declare -A var; is-var-set B # apparently no way to just _check_ its existence
这是输出 .
1: var's unset. ${var+x}= ${#var[@]}=0
2: var is set. ${var+x}=x ${#var[@]}=1
3: var is set. ${var+x}=x ${#var[@]}=1
4: var's unset. ${var+x}= ${#var[@]}=0
5: var is set. ${var+x}=x ${#var[@]}=1
6: var is set. ${var+x}=x ${#var[@]}=1
7: Is var set? ${var+x}= ${#var[@]}=1
8: var's unset. ${var+x}= ${#var[@]}=0
9: var's unset. ${var+x}= ${#var[@]}=0
A: Is var set? ${var+x}= ${#var[@]}=1
./foo.sh: line 26: declare: var: cannot convert indexed to associative array
B: var's unset. ${var+x}= ${#var[@]}=0
这两种语法都没有解释如果使用了 declare -a var 会发生什么,而不在数组中的某处分配空值 . Bash仍然在某处区分案例(如上面的测试 B 所示),所以这个答案's not foolproof. Fortunately Bash converts exported environment variables into strings when running a program/script, so any issues with declared-but-unset variables will be contained to a single script, at least if it'不是采购其他脚本 .
-1
要检查非null /非零字符串变量,即如果设置,请使用
if [ -n "$1" ]
这与 -z 相反 . 我发现自己使用 -n 超过 -z .
您会像以下一样使用它:
if [ -n "$1" ]; then
echo "You supplied the first parameter!"
else
echo "First parameter not supplied."
fi
163
如果你想检查 $@ 中的任何内容,我发现了一个(很多)更好的代码 .
if [[ $1 = "" ]]
then
echo '$1 is blank'
else
echo '$1 is filled up'
fi
为什么这一切? $@ 中的所有内容都存在于Bash中,但默认情况下它是空白的,因此 test -z 和 test -n 无法帮助您 .
Update: 您还可以计算参数中的字符数 .
if [ ${#1} = 0 ]
then
echo '$1 is blank'
else
echo '$1 is filled up'
fi
阅读 bash 手册页的"Parameter Expansion"部分 . 参数扩展没有设置't provide a general test for a variable being set, but there are several things you can do to a parameter if it isn't .
例如:
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
}
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
1740
如果您希望测试变量是绑定还是未绑定,那么即使您打开了nounset选项,这也很有效:
set -o noun set
if printenv variableName >/dev/null; then
# variable is bound to a value
else
# variable is unbound
fi
0
这就是我每天都在使用的东西:
#
# Check if a variable is set
# param1 name of the variable
#
function is_set()
{
[[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}
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
31
我喜欢辅助函数来隐藏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} ]
}
#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
1
您可以做:
function a {
if [ ! -z "$1" ]; then
echo '$1 is set'
fi
}
# 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的数据永远不会,因为只有在未设置变量或空数组时才会调用declare .
此功能将在以下条件中进行测试:
a; #未声明 A =; #被声明 一个= “foo” 的; #被声明 A =(); #被声明 A =( “”); #被声明 未设置#未声明
一个; #未设置 A =; #没有未设置 一个= “foo” 的; #没有未设置 A =(); #没有未设置 A =( “”); #没有未设置 未设置#未设置
30 回答
虽然对于参数,我认为通常最好测试$#,即参数的数量 .
启用Bash选项
set -u
时,上述答案不起作用 . 此外,它们不是动态的,例如,如何测试变量,名称"dummy"是否已定义?试试这个:相关:In Bash, how do I test if a variable is defined in "-u" mode
如果未设置,您想要退出
这对我有用 . 如果未设置参数,我希望我的脚本退出并显示错误消息 .
运行时返回错误
仅检查,无退出 - 空和未设置为无效
如果您只想检查值set = VALID或unset / empty = INVALID,请尝试此选项 .
或者,即使是短暂的测试;-)
仅检查,无退出 - 仅空为INVALID
这就是问题的答案 . 如果您只想检查值set / empty = VALID或unset = INVALID,请使用此选项 .
注意,“..- 1}”中的“1”是无关紧要的,它可以是任何东西(如x)
简短的测试
我把这个答案献给了@ mklement0(评论),他们挑战我准确地回答这个问题 .
参考http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
(通常)正确的方式
其中
${var+x}
是parameter expansion,如果未设置var
,则计算结果为空,否则替换字符串x
.报价题外话
引号可以省略(所以我们可以说
${var+x}
而不是"${var+x}"
),因为这种语法和用法保证只会扩展到不需要引号的东西(因为它扩展为x
(它不包含分词,所以它不需要引号) ,或者什么都没有(导致[ -z ]
,方便地计算[ -z "" ]
所做的相同值(true))) .然而,尽管可以安全地省略引号,并且它并不是立即显而易见的(对于the first author of this quotes explanation谁也是一个主要的Bash编码器来说甚至都不明显),有时候用引号编写解决方案更好
[ -z "${var+x}" ]
,at O(1)速度惩罚的可能成本非常小 . 第一作者还在代码旁边添加了这个注释,使用此解决方案给出了这个答案的URL,现在还包括为什么可以安全地省略引号的解释 .(经常)错误的方式
这通常是错误的,因为它不区分未设置的变量和设置为空字符串的变量 . 也就是说,如果
var=''
,那么上面的解决方案将输出"var is blank" .在用户必须指定扩展名或其他属性列表并且未指定它们默认为非空值的情况下,unset和“设置为空字符串”之间的区别是必不可少的,而指定空字符串应该使脚本使用空扩展或其他属性列表 .
但是,在每种情况下,这种区别可能并不重要 . 在那些情况下
[ -z "$var" ]
会没事的 .要检查变量是否设置为非空值,请使用
[ -n "$x" ]
,正如其他人已经指出的那样 .大多数情况下,以与未设置的变量相同的方式处理具有空值的变量是个好主意 . 但是如果需要,你可以区分这两个:
[ -n "${x+set}" ]
("${x+set}"
如果x
设置则扩展为set
,如果未设置x
则扩展为空字符串) .要检查参数是否已通过,请测试
$#
,这是传递给函数的参数数量(或不在函数中时的脚本)(请参阅Paul's answer) .以下是测试参数是 unset ,还是 empty ("Null") 或 set with a value 的方法:
资料来源:POSIX: Parameter Expansion:
在bash中你可以在
[[ ]]
内置中使用-v
:我最喜欢的方式是:
所以基本上,如果设置了一个变量,它就会变成“对结果
false
的否定”(这将是true
= "is set") .并且,如果它未被设置,它将变为“对结果
true
的否定”(因为空结果的计算结果为true
)(因此将结束为false
= "NOT set") .要么
要么
要么
我总是使用这个,基于以下事实:任何第一次看到代码的人都很容易理解它:
并且,如果想要检查是否为空;
而已 .
如果
var
可以是数组,则[ -z "${var+x}" ]
参数替换不正确 . 要确保在Bash中你需要使用array syntax,如[ "${#var[@]}" = 0 ]
,如下所示 .几乎在所有情况下,他们都同意 . 我发现数组方法更准确的唯一情况是变量是一个带位置的非空数组
0
未设置(例如,在下面的测试7
和A
中) . 这种分歧来自$var
是${var[0]}
的简写,所以[ -z "${var+x}" ]
没有检查整个数组 .这是我的测试用例 .
这是输出 .
总共:
${var+x}
参数扩展语法在大多数情况下与${#var[@]}
数组语法一样有效,例如检查函数的参数 . 这种情况可能破坏的唯一方法是,如果未来版本的Bash添加了一种将数组传递给函数而不将内容转换为单个参数的方法 .非空数组(关联或非关联)与元素
0
unset需要数组语法 .这两种语法都没有解释如果使用了
declare -a var
会发生什么,而不在数组中的某处分配空值 . Bash仍然在某处区分案例(如上面的测试B
所示),所以这个答案's not foolproof. Fortunately Bash converts exported environment variables into strings when running a program/script, so any issues with declared-but-unset variables will be contained to a single script, at least if it'不是采购其他脚本 .要检查非null /非零字符串变量,即如果设置,请使用
这与
-z
相反 . 我发现自己使用-n
超过-z
.您会像以下一样使用它:
如果你想检查
$@
中的任何内容,我发现了一个(很多)更好的代码 .为什么这一切?
$@
中的所有内容都存在于Bash中,但默认情况下它是空白的,因此test -z
和test -n
无法帮助您 .Update: 您还可以计算参数中的字符数 .
有很多方法可以做到这一点,其中之一是:
如果$ 1为null或未设置,则成功
对于那些希望在带有set -u的脚本中检查未设置 or empty 的人:
常规
[ -z "$var" ]
检查将失败var; unbound variable
如果set -u
但[ -z "${var-}" ]
expands为空字符串如果var
未设置而没有失败 .为了查看变量是否为非空,我使用
如果变量未设置或为空,则相反测试:
要查看是否设置了变量(空或非空),我使用
相反的测试是否未设置变量:
使用
[[ -z "$var" ]]
是了解变量是否设置的最简单方法,但该选项-z
不区分未设置变量和设置为空字符串的变量:最好根据变量的类型进行检查:env变量,参数或常规变量 .
对于env变量:
对于参数(例如,检查参数
$5
的存在):对于常规变量(使用辅助函数,以优雅的方式执行):
笔记:
虽然这里陈述的大多数技术都是正确的,但 bash 4.2 支持对变量(man bash)的存在进行实际测试,而不是测试变量的值 .
阅读
bash
手册页的"Parameter Expansion"部分 . 参数扩展没有设置't provide a general test for a variable being set, but there are several things you can do to a parameter if it isn't .例如:
如果已分配
first_arg
将等于$1
,否则它将使用值"foo" . 如果a
绝对必须采用单个参数,并且不存在良好的默认值,则可以在未给出参数时退出并显示错误消息:(注意使用
:
作为空命令,它只是扩展其参数的值 . 在这个例子中我们不想对$1
做任何事情,如果没有设置就退出)在Bash的现代版本(我认为4.2或更高版本;我不确定),我会尝试这样做:
如果您希望测试变量是绑定还是未绑定,那么即使您打开了nounset选项,这也很有效:
这就是我每天都在使用的东西:
这在Linux和Solaris下适用于bash 3.0 .
我喜欢辅助函数来隐藏bash的粗略细节 . 在这种情况下,这样做会增加更多(隐藏)粗糙:
因为我在这个实现中首先遇到了错误(受到Jens和Lionel的答案的启发),我想出了一个不同的解决方案:
我发现它更直接,更邋and,更容易理解/记忆 . 测试用例显示它是等效的:
测试用例还显示
local var
确实 NOT 声明var(除非后跟'=') . 很长一段时间以来,我以为我用这种方式声明了变量,现在才发现我只是表达了我的意图......我猜这是一个无操作 .BONUS: usecase
我主要使用这个测试以一种有点"elegant"安全的方式给函数赋予(和返回)参数(几乎类似于接口......):
如果调用所有声明的需求变量:
其他:
您可以做:
在shell中,您可以使用
-z
运算符,如果字符串的长度为零,则该运算符为True .一个简单的单行设置默认
MY_VAR
如果没有设置,否则可选择显示消息:我总是发现other answer中的POSIX表很慢,所以这是我对它的看法:
请注意,每个组(有和没有前置冒号)具有相同的set和unset情况,因此唯一不同的是如何处理空案例 .
对于前面的冒号,空和未设置的情况是相同的,所以我会尽可能使用那些(即使用
:=
,而不仅仅是=
,因为空的情况不一致) .Headings:
set表示
VARIABLE
非空(VARIABLE="something"
)空表示
VARIABLE
为空/ null(VARIABLE=""
)unset表示
VARIABLE
不存在(unset VARIABLE
)Values:
$VARIABLE
表示结果是变量的原始值 ."default"
表示结果是提供的替换字符串 .""
表示结果为null(空字符串) .exit 127
表示脚本停止执行,退出代码为127 .$(VARIABLE="default")
表示结果是变量的原始值,并且提供的替换字符串将分配给变量以供将来使用 .用于检查变量是否已声明/未设置的函数
包括空$ array =()
以下函数测试给定名称是否作为变量存在
首先测试变量是否设置(un),如果没有必要,可以避免声明调用 .
但是如果
$1
包含空$array=()
的名称,则声明的调用将确保我们得到正确的结果传递给/ dev / null的数据永远不会,因为只有在未设置变量或空数组时才会调用declare .
此功能将在以下条件中进行测试:
一个; #未设置
A =; #没有未设置
一个= “foo” 的; #没有未设置
A =(); #没有未设置
A =( “”); #没有未设置
未设置#未设置
.