2

I'm trying to figure out how to declare a variable without assigning a value to it. According to the bash doc, that should be ok:

declare [-aAfFgilnrtux] [-p] [name[=value] ...]

Declare variables and/or give them attributes.

The "=value" bit is optional, but using "declare var" without an assignment doesn't seem to do anything.

#!/bin/bash

function check_toto_set() {
  if [ -z "${toto+x}" ] ; then
    echo toto not defined!
  else
    echo toto=$toto
    echo toto defined, unsetting
    unset toto
  fi
}

function set_toto() {
  declare -g toto
}

function set_toto_with_value() {
  declare -g toto=somevalue
}

check_toto_set
toto=something
check_toto_set
declare toto
check_toto_set
set_toto
check_toto_set
set_toto_with_value
check_toto_set

Basically I would expect to have "toto not defined!" just for the first "check_toto_set", and all the others should find toto being declared, even if empty but the ouput is:

toto not defined!
toto=something
toto defined, unsetting
toto not defined!
toto not defined!
toto=somevalue
toto defined, unsetting

I'm using bash 4.3.46 on ubuntu

echo $BASH_VERSION
4.3.46(1)-release

So am I misunderstanding something about declare, or am I testing if a variable is set the wrong way? (I'm using info from How to check if a variable is set in Bash? for that)

1
  • BTW, unset effectively undeclares a variable; it doesn't just remove the value. Commented Mar 9, 2017 at 22:01

1 Answer 1

3

You're testing if the variable is set (even to an empty value). That's different from whether it has been declared.

To determine whether it has been declared, you can use declare -p:

varstat() {
  if declare -p "$1" >/dev/null 2>&1; then
    if [[ ${!1+x} ]]; then
      echo "set"
    else
      echo "declared but unset"
    fi
  else
    echo "undeclared"
  fi
}

export -f varstat

bash -c 'varstat toto'                 # output: "undeclared"
bash -c 'declare toto; varstat toto'   # output: "declared but unset"
bash -c 'declare toto=; varstat toto'  # output: "set"
Sign up to request clarification or add additional context in comments.

4 Comments

This should work but somehow when i tried it worked in BASH 3 but not BASH4
@XSen, exported functions don't work across version boundaries (well, not that particular version boundary; the format was reworked due to shellshock). Thus, the shell in which you run export -f varstat needs to be the same major version as the one invoked by bash -c.
I'm just testing with "declare toto ; declare -p toto" in the shell, with no function. Somehow this doesn't work with 4.3.46(1)-release shipped with ubuntu LTS 16.04. But I've downloaded the sourcecode for bash 4.4.0 from gnu.org, built it and tried it in there, and it works.... so there is some funny stuff going in on with the packaged versions (didn't work at work on a redhat 4.1.x either...)
shrug. declareing isn't really very useful if you aren't adding flags (declare -x, declare -i, etc) -- I'm not immensely surprised to see a corner case. (Since variables in shell are global by default, inside a function it's necessary for declare foo to cause a change in state -- by marking it local -- but if declare -g foo is a noop, it has no real impact in terms of documented semantics).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.