0

As https://stackoverflow.com/a/13864829/ said,

$ if [ -z ${aaa+x} ]; then echo "aaa is unset"; else echo "aaa is set"; fi 
aaa is unset

can test if a variable aaa is set or unset.

How can I wrap the checking into a function? In bash, the following nested parameter expansion doesn't work:

$ function f() { if [ -z ${$1+x} ]; then echo "$1 is unset"; else echo "$1 is set"; fi }; 
$ f aaa
bash: ${$1+x}: bad substitution

Thanks.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Tim
  • 101,790

2 Answers2

3

Use indirection:

function f() { if [ -z "${!1+x}" ]; then echo "$1 is unset"; else echo "$1 is set"; fi };

This tests against the variable named by the first parameter of the function. You may want to sanity-check that the user has provided an argument to the function.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
3

The -v test in bash will be true if the named variable has been set.

if [ -v aaa ]; then
    echo 'The variable aaa has been set'
fi

From help test in bash:

-v VAR True if the shell variable VAR is set.

As a function:

testset () {
    if [ -v "$1" ]; then
        printf '%s is set\n' "$1"
    else
        printf '%s is not set\n' "$1"
    fi
}

As a script for sourcing:

if [ -v "$1" ]; then
    printf '%s is set\n' "$1"
else
    printf '%s is not set\n' "$1"
fi

Using this last script:

source ./settest variablename
Kusalananda
  • 333,661
  • Thanks. I was wondering how you store the code in your reply for reuse in other scripts or shells https://unix.stackexchange.com/questions/481760/writing-a-script-containing-just-one-function-definition-v-s-moving-the-code-in – Tim Nov 14 '18 at 18:36
  • @Tim I'm not sure I understand your question. In this case, I would actually not write a function as it's an intrinsic function of the bash shell. Wrapping it in a function would serve no benefit. – Kusalananda Nov 14 '18 at 19:07
  • Thanks. How would you store the code in the function body? I put it in a script. I just source the script with an argument being a variable's name. – Tim Nov 14 '18 at 19:47
  • @Tim I'm still a bit uncertain what you mean. If you source the function definition, then the function would be callable in the current script. – Kusalananda Nov 14 '18 at 19:50
  • (1) First of all, I am very forgetful, and if I need some command to do something, I can't quickly find it. I don't know a better way than storing code into script files, even for simple code like the one here . (2) If a script only contains the definition of a function, we can alternatively write a script without the definition of a function but with the code in the function's body moved directly into the script, and use the script by sourcing it with argument(s). That is what I was asking in the link. – Tim Nov 14 '18 at 19:55
  • @Tim Is what I have just added to the answer what you are looking for? – Kusalananda Nov 14 '18 at 20:11
  • I also did it that way. But I am not sure which one is better: that way (only script without function definition), or wrap the code in a function and put the function in a script, and then source the script and call the function with arguments. – Tim Nov 14 '18 at 20:41
  • @Tim If I really wanted to wrap this test in any sort of way (as I personally would not do), I would wrap it in a function. That function may live in a separate script if I wanted to reuse it in other scripts, and each script would source it to be able to later call the function. That would be the most efficient. – Kusalananda Nov 14 '18 at 20:46