我如何知道是否在Bash中设置了变量?

例如,如何检查用户是否向函数提供了第一个参数?

function a {
    # if $1 is set ?
}

当前回答

要检查变量是否设置为非空值,请使用[-n“$x”],正如其他人已经指出的那样。

大多数情况下,最好将具有空值的变量与未设置的变量以相同的方式处理。但如果需要,您可以区分这两个:[-n“${x+set}”](如果设置了x,则“${x+set}”扩展为set,如果未设置x,则扩展为空字符串)。

要检查是否传递了参数,请测试$#,这是传递给函数(或不在函数中时传递给脚本)的参数数(请参见Paul的答案)。

其他回答

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

在shell中,可以使用-z运算符,如果字符串长度为零,则该运算符为True。

如果未设置默认MY_VAR,则使用一个简单的单行设置,否则您可以选择显示消息:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."

我总是发现另一个答案中的POSIX表很难找到,所以我的看法是:

parameter expansion VARIABLE set VARIABLE empty VARIABLE 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" "" ""

请注意,每个组(前面有和没有冒号)都有相同的设置和未设置的大小写,因此唯一不同的是如何处理空大小写。

对于前面的冒号,空的和未设置的大小写是相同的,因此我将在可能的情况下使用它们(即使用:=,而不仅仅是=,因为空的大小写不一致)。

标题:

set表示VARIABLE为非空(VARIABLE=“something”)空表示VARIABLE为空/空(VARIABLE=“”)未设置表示变量不存在(未设置变量)

值:

$VARIABLE表示结果是变量的原始值。“默认”表示结果是提供的替换字符串。“”表示结果为空(空字符串)。退出127意味着脚本停止执行,退出代码127。$(VARIABLE=“默认”)表示结果为“默认”,VARIABLE(以前为空或未设置)也将设置为“默认值”。

有许多方法可以做到这一点,以下是其中之一:

if [ -z "$1" ]

如果$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} ]
}

因为我在这个实现中首先遇到了bug(灵感来自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

测试用例还显示,局部var不声明var(除非后面跟着“=”)。很长一段时间以来,我以为我是这样声明变量的,只是为了发现我只是表达了我的意图。。。我想这是不可能的。

IsDeclared_Tricky xyz:1IsDeclared_Tricky foo:1IsDeclared_Tricky条:0我声明的Tricky baz:0IsDeclared xyz:1IsDeclared foo:1IsDeclared栏:0IsDeclared 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 the error
  exampleFunction
  echo $outputStr
}

bonus

如果调用时声明了所有必需的变量:

你好,世界!

其他:

错误:未声明变量:outputStr