Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if an associative array exists

Tags:

bash

Since bash 4.2, the -v conditional expression has been added. It's used to check if a variable is set (has been assigned a value). It's a useful tool when writing scripts that run under set -o nounset, because attempting to use a non-initialized variable causes an error.

I have one issue with it, see the sample in a POSIX bash (set -o posix):

$ declare testvar=0
$ [ -v testvar ] && echo "It works!"
It works!
$ declare -A fizz=( [buzz]=jazz )
$ [ -v fizz[buzz] ] && echo "It works!"
It works!
$ [ -v fizz ] && echo "It doesn't work :("
$ 

As you can see, using -v on a regular variable works as expected. Using it to check the presence of a field within an associative array works as expected as well. However, when checking the presence of the associative array itself, it doesn't work.

Why is that, and is there a workaround?

like image 356
T. Barusseau Avatar asked Dec 12 '19 12:12

T. Barusseau


People also ask

How do you find an associative array?

How to check if PHP array is associative or sequential? There is no inbuilt method in PHP to know the type of array. If the sequential array contains n elements then their index lies between 0 to (n-1). So find the array key value and check if it exist in 0 to (n-1) then it is sequential otherwise associative array.

How do you check if a value exists in an associative array in PHP?

The in_array() function is an inbuilt function in PHP that is used to check whether a given value exists in an array or not. It returns TRUE if the given value is found in the given array, and FALSE otherwise.

Does In_array work for associative array?

in_array() function is utilized to determine if specific value exists in an array. It works fine for one dimensional numeric and associative arrays.

Is associative array in PHP?

PHP treats all arrays as associative, so there aren't any built in functions.


1 Answers

If you want to know if it has any entries, you can check ${#fizz[@]}, but that doesn't tell you if it has been created empty. You can use a case statement or other pattern matching in conjunction with error checking.

tst() { local tst;   
  (( $# )) || return                             # *minimal* error handling...
  if tst="$(declare -p $1 2>&1)"                 # does the subshell error?
  then case "$tst" in                            # if not, check the output
       *\)*) (( $( eval echo \${#$1[@]} ) )) &&  # test number of entries
                echo "Has Args"              ||  # some implementations show '()'
                echo "Empty but defined";;       # some don't; this is for the *do*
       *-A*) echo "Empty but defined";;          # this is for the don't
          *) echo ERROR;;                        # shouldn't get here
       esac
  else echo Undefined                            # if doesn't exist
  fi
}


$: unset fizz
$: tst fizz
Undefined
$: declare -A fizz
$: tst fizz
Empty but defined
$: fizz[buzz]=jazz
$: tst fizz
Has Args

Dunno how useful that will be in your context though. Note that I wrote this one explicitly for associative arrays with minimal error checking not directly related to the point. For any sort of real production use this should be expanded a lot.

I don't like the eval, but my bash version doesn't have namerefs. :o/

like image 198
Paul Hodges Avatar answered Sep 19 '22 14:09

Paul Hodges