web-dev-qa-db-fra.com

Vérification Bash si la variable est un tableau

J'ai une boucle sur les noms de variables et je dois vérifier si une variable désignée par ce nom est un tableau ou non. J'ai essayé de chercher sur Google mais je n'ai rien trouvé. De l'aide?

for varname in AA BB CC; do
  local val
  if [ "$varname" is array ]; then # how can I perform this test?
    echo do something with an array
  else
    echo do something with a "'normal'" variable
  fi
done
27
wujek

Google peut être votre ami

declare -p variable-name 2> /dev/null | grep -q '^declare \-a'
12
Bastien Jansen

Pour éviter un appel à grep, vous pouvez utiliser:

if [[ "$(declare -p variable_name)" =~ "declare -a" ]]; then
    echo array
else
    echo no array
fi
29
Reuben W

Depuis bash 4.3, ce n’est plus aussi simple que cela.

Avec "declare -n", vous pouvez ajouter une référence à une autre variable et le faire encore et encore. Comme si ce n'était pas assez compliqué, avec "declare -p", vous n'obtenez pas le type ou la variable d'origine.

Exemple: 

$ declare -a test=( a b c d e)
$ declare -n mytest=test
$ declare -n newtest=mytest
$ declare -p newtest
declare -n newtest="mytest"
$ declare -p mytest
declare -n mytest="test"

Par conséquent, vous devez parcourir toutes les références. En bash seulement cela ressemblerait à ceci: 

vartype() {
    local var=$( declare -p $1 )
    local reg='^declare -n [^=]+=\"([^\"]+)\"$'
    while [[ $var =~ $reg ]]; do
            var=$( declare -p ${BASH_REMATCH[1]} )
    done

    case "${var#declare -}" in
    a*)
            echo "ARRAY"
            ;;
    A*)
            echo "HASH"
            ;;
    i*)
            echo "INT"
            ;;
    x*)
            echo "EXPORT"
            ;;
    *)
            echo "OTHER"
            ;;
    esac
}

Avec l'exemple ci-dessus:

$ vartype newtest
ARRAY

Pour vérifier le tableau, vous pouvez modifier le code ou l'utiliser avec grep: 

vartype $varname | grep -q "ARRAY"
7
Marco

J'ai commencé avec Reuben excellente réponse ci-dessus. J'ai implémenté quelques-uns des commentaires et certaines de mes propres améliorations.

#!/bin/bash
array_test() {
    # no argument passed
    [[ $# -ne 1 ]] && echo 'Supply a variable name as an argument'>&2 && return 2
    var=$1
    # use a variable to avoid having to escape spaces
    regex="^declare -[aA] ${var}(=|$)"
    [[ $(declare -p "$var" 2> /dev/null) =~ $regex ]] && return 0
}

Maintenant je peux faire ça:

foo=(lorem ipsum dolor)
bar="declare -a tricky"
declare -A baz

array_test foo && echo "it's an array"
array_test bar && echo "it's an array"
# properly detects empty arrays
array_test baz && echo "it's an array"
# won't throw errors on undeclared variables
array_test foobarbaz && echo "it's an array"
0
miken32
is_array() {
  local variable_name=$1
  [[ "$(declare -p $variable_name)" =~ "declare -a" ]]
}

is_array BASH_VERSINFO && echo BASH_VERSINFO is an array

is_array() {
    local variable_name=$1
    [[ "$(declare -p $variable_name 2>/dev/null)" =~ "declare -a" ]]
}
0
dawesh