In Bash, how do I test if a variable is defined in “-u” mode

后端 未结 7 1927
傲寒
傲寒 2020-12-23 09:14

I just discovered set -u in bash and it helped me find several previously unseen bugs. But I also have a scenario where I need to test if a variable is defined

相关标签:
7条回答
  • 2020-12-23 09:54

    What Doesn't Work: Test for Zero-Length Strings

    You can test for undefined strings in a few ways. Using the standard test conditional looks like this:

    # Test for zero-length string.
    [ -z "$variable" ] || variable='foo'
    

    This will not work with set -u, however.

    What Works: Conditional Assignment

    Alternatively, you can use conditional assignment, which is a more Bash-like way to do this. For example:

    # Assign value if variable is unset or null.
    : "${variable:=foo}"
    

    Because of the way Bash handles expansion of this expression, you can safely use this with set -u without getting a "bash: variable: unbound variable" error.

    0 讨论(0)
  • 2020-12-23 09:59

    In bash 4.2 and newer there is an explicit way to check whether a variable is set, which is to use -v. The example from the question could then be implemented like this:

    if [[ ! -v variable ]]; then
       variable="$(...)"
    fi
    

    See http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions

    If you only want to set the variable, if it is not already set you are probably better of doing something along these lines:

    variable="${variable-$(...)}"

    Note that this does not deal with a defined but empty variable.

    0 讨论(0)
  • 2020-12-23 10:00

    This is what I've found works best for me, taking inspiration from the other answers:

    if [ -z "${varname-}" ]; then
      ...
      varname=$(...)
    fi
    
    0 讨论(0)
  • 2020-12-23 10:05

    In the beginning of your script, you could define your variables with an empty value

    variable_undefined=""
    

    Then

    if [ "${variable_undefined}" == "" ]; then
        variable="$(...)"
    fi
    
    0 讨论(0)
  • 2020-12-23 10:08
    if [ "${var+SET}" = "SET" ] ; then
        echo "\$var = ${var}"
    fi
    

    I don't know how far back ${var+value} is supported, but it works at least as far back as 4.1.2. Older versions didn't have ${var+value}, they only had ${var:+value}. The difference is that ${var:+value} will only evaluate to "value" if $var is set to a nonempty string, while ${var+value} will also evaluate to "value" if $var is set to the empty string.

    Without [[ -v var ]] or ${var+value} I think you'd have to use another method. Probably a subshell test as was described in a previous answer:

    if ( set -u; echo "$var" ) &> /dev/null; then
        echo "\$var = ${var}
    fi
    

    If your shell process has "set -u" active already it'll be active in the subshell as well without the need for "set -u" again, but including it in the subshell command allows the solution to also work if the parent process hasn't got "set -u" enabled.

    (You could also use another process like "printenv" or "env" to test for the presence of the variable, but then it'd only work if the variable is exported.)

    0 讨论(0)
  • 2020-12-23 10:10

    Unfortunatly [[ -v variable ]] is not supported in older versions of bash (at least not in version 4.1.5 I have on Debian Squeeze)

    You could instead use a sub shell as in this :

    if (true $variable)&>/dev/null; then
        variable="$(...)"
    fi
    
    0 讨论(0)
提交回复
热议问题