0

Does declare -p check if a variable (including an array variable) is set?

Why does it behave differently for an array variable and a non-array variable?

For an array variable:

$ unset ar
$ declare -a ar=()
$ declare -p ar
declare -a ar='()'
$ echo ${ar[@]-This is a new value}
This is a new value

and

$ unset ar
$ declare -a ar
$ declare -p ar
bash: declare: ar: not found
$ echo ${ar[@]-This is a new value}
This is a new value

For a non-array variable:

$ unset var
$ declare -i var
$ declare -p var
bash: declare: var: not found
$ echo ${var-This is a new value}
This is a new value

Thanks.


I am running Bash 4.3.48.

From https://unix.stackexchange.com/a/381491/674, I heard that in 4.4, after running unset ar and declare -a ar, the output of running declare -p var is declare -a ar.

I would like to know whether declare -p in bash 4.4. handles array differently from other types. In 4.4, after running unset var and declare -i var , what is the output of running declare -p var. Does it output error such as bash: declare: var: not found or declare -i var?

  • You didn't unset the array variable ar before testing for it's presence using the declare -p command. Also, why declare -a ar='()'? a mere, declare -p ar should suffice. – user218374 Jul 24 '17 at 18:21
  • Only bash 4.3 reports an error if ar was set with declare -a ar, but no error if the array was defined with declare -a ar=(). – Arrow Jul 25 '17 at 0:07
2

All bash versions do handle arrays correctly if the array is given a list ().
Or an array element is given a value (even null).
This code (using typeset to get it to run in ksh):

unset ar; typeset -a ar=()
printf '%-20s%s ' "$(typeset -p ar)" '--'

unset ar; typeset -a ar; ar[3]=""
printf '%-30s%s ' "$(typeset -p ar)" '@@'

unset ar; typeset -a ar; ar[3]="val"
printf '%-31s ' "$(typeset -p ar)"

Will print this results:

zsh/sh          : typeset -a ar=(  )  -- typeset -a ar=( '' '' '' '' ) @@ typeset -a ar=( '' '' '' val )
b203sh          : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b204sh          : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b205sh          : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b30sh           : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b32sh           : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b41sh           : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b42sh           : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b43sh           : declare -a ar='()'  -- declare -a ar='([3]="")'      @@ declare -a ar='([3]="val")'
b44sh           : declare -a ar=()    -- declare -a ar=([3]="")        @@ declare -a ar=([3]="val")
ksh93           : typeset -a ar       -- typeset -a ar=([3]='')        @@ typeset -a ar=([3]=val)
attsh           : typeset -a ar       -- typeset -a ar=([3]='')        @@ typeset -a ar=([3]=val)
zsh/ksh         : typeset -a ar=(  )  -- typeset -a ar=( '' '' '' '' ) @@ typeset -a ar=( '' '' '' val )
zsh             : typeset -a ar=(  )  -- typeset -a ar=( '' '' '' )    @@ typeset -a ar=( '' '' val )

As you can see, all shells (with some diferences) run the code and provide equivalent results.


Also, all shells work with this code:

unset ar; typeset -i ar              ; printf '%-17s%s ' "$(typeset -p ar)" '=='
unset ar; typeset -a ar              ; printf '%-19s%s ' "$(typeset -p ar)" '++'

And print:

zsh/sh          : typeset -i ar=0  == typeset -a ar=(  ) ++
b203sh          : declare -i ar="" == declare -a ar='()' ++
b204sh          : declare -i ar="" == declare -a ar='()' ++
b205sh          : declare -i ar="" == declare -a ar='()' ++
b30sh           : declare -i ar="" == declare -a ar='()' ++
b32sh           : declare -i ar="" == declare -a ar='()' ++
b44sh           : declare -i ar    == declare -a ar      ++
ksh93           : typeset -i ar    == typeset -a ar      ++
attsh           : typeset -i ar    == typeset -a ar      ++
zsh/ksh         : typeset -i ar=0  == typeset -a ar=(  ) ++
zsh             : typeset -i ar=0  == typeset -a ar=(  ) ++

The rough patch is in bash series 4. Both 4.1 and 4.2 work for the array:

b41sh           : declare -a ar='()' ++
b42sh           : declare -a ar='()' ++

But not for a simple variable. And bash 4.3 fails in both tests:

b43sh           : script: line 3: typeset: ar: not found ==
                  script: line 4: typeset: ar: not found ++

So, for this tests, please move out of Bash 4.3 --.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.