bash - shell variable from command output




如何檢查變量是否設置在Bash中? (20)

Functions to check if variable is declared/unset

including empty $array=()


The following functions test if the given name exists as a variable

# 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;} 
}
  • By first testing if the variable is (un)set, the call to declare can be avoided, if not necessary.
  • If however $1 contains the name of an empty $array=() , the call to declare would make sure we get the right result
  • There's never much data passed to /dev/null as declare is only called if either the variable is unset or an empty array.

This functions would test as showed in the following conditions:

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

For more details

and a test script see my answer to the question "How do I check if a variable exists in bash?"

備註:declare -p正如的answer顯示的,類似的用法確實是巧合。否則,我當然會相信它!

我如何知道是否在Bash中設置了一個變量?

例如,如何檢查用戶是否將第一個參數提供給函數?

function a {
    # if $1 is set ?
}

如果未設置,您想退出

這對我有效。 如果沒有設置參數,我希望腳本退出並顯示錯誤消息。

#!/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}"

運行時會返回一個錯誤

[email protected]:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

僅檢查,不退出 - Empty和Unset無效

如果您只想檢查set 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


I like auxiliary functions to hide the crude details of bash. In this case, doing so adds even more (hidden) crudeness:

# 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} ]
}

Because I first had bugs in this implementation (inspired by the answers of Jens and Lionel), I came up with a different solution:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

I find it to be more straight-forward, more bashy and easier to understand/remember. Test case shows it is equivalent:

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

The test case also shows that local var does NOT declare var (unless followed by '='). For quite some time I thought i declared variables this way, just to discover now that i merely expressed my intention... It's a no-op, i guess.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
IsDeclared bar: 0
IsDeclared baz: 0

BONUS: usecase

I mostly use this test to give (and return) parameters to functions in a somewhat "elegant" and safe way (almost resembling an interface...):

#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

If called with all requires variables declared:

Hello world!

其他:

Error: variable not declared: outputStr


If you wish to test that a variable is bound or unbound, this works well, even after you've turned on the nounset option:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi

你可以做:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}

使用[[ -z "$var" ]]是知道變量是否被設置的最簡單方法,但該選項不區分未設置的變量和設置為空字符串的變量:

 set=''

 $ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
 Unset

 $ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
 Unset

最好根據變量類型來檢查它:env變量,參數或常規變量。

對於env變量:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

對於參數(例如,檢查是否存在參數“$ 5”:

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

對於常規變量(使用輔助功能,以優雅的方式進行):

function declare_var {
   declare -p "$1" &> /dev/null

   return $?
}

declare_var "var_name" && echo "Set" || echo "Unset"

筆記:

$#                  says you the number of positional parameters.

declare -p          gives you the definition of the variable passed as parameter. If it 
                    exists, returns 0, if not, returns 1 and prints an error message.

$?                  gives you the status code of the last executed command.

在shell中,可以使用-z運算符,如果字符串的長度為零,則該運算符為True。

如果未設置默認MY_VAR ,可以使用簡單的單行設置,否則可以選擇顯示消息:

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

在現代版本的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

如果你想檢查[email protected]任何內容,我發現了一個(更好)更好的代碼。

if [[ $1 = "" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

為什麼這一切? [email protected]所有內容都存在於Bash中,但默認情況下它是空白的,所以test -ztest -n無法幫助你。

更新:您也可以統計參數中的字符數。

if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

對於那些在set -u的腳本中查找未設置或空的時候:

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

常規的[ -z "$var" ]檢查將失敗, var; unbound variable 如果set -u則為非var; unbound variable ,但如果var var; unbound variable set -u var; unbound variable set -u ,則[ -z "${var-}" ] expands為空字符串。


我總是使用這個,基於這樣一個事實:任何人第一次看到代碼似乎都很容易理解:

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

而且,如果想檢查是否不為空;

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

而已。


我總是發現其他答案中的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")表示結果是變量的原始值, 並且提供的替換字符串被分配給該變量以備將來使用。

為了查看一個變量是否為非空,我使用

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

當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.
}

相關: 在Bash中,如何測試變量是否在“-u”模式下定義


要檢查非空/非零字符串變量,即如果設置,請使用

if [ -n "$1" ]

這與-z相反。 我發現自己使用-n多於-z


這就是我每天都在使用的東西:

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}

這在Linux和Solaris下運行良好,最終崩潰到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 4.2支持對變量( man bash )的存在進行實際測試,而不是測試變量的值。

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

[[ $foo ]]

要么

(( ${#foo} ))

要么

let ${#foo}

要么

declare -p foo

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

if [[ ${!xx[@]} ]] ; then echo xx is defined; fi




variables