web-dev-qa-db-de.com

Bash-Prüfung, ob Variable Array ist

Ich habe eine Schleife über Variablennamen und muss überprüfen, ob eine Variable, auf die dieser Name verweist, ein Array ist oder nicht. Ich versuchte es zu googeln, konnte aber nichts finden. Irgendeine Hilfe?

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 kann sein dein Freund

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

Um einen Anruf bei grep zu vermeiden, können Sie Folgendes verwenden:

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

Seit Bash 4.3 ist das nicht mehr so ​​einfach.

Mit "declare -n" können Sie einen Verweis auf eine andere Variable hinzufügen und dies immer wieder tun. Als wäre dies nicht kompliziert genug, erhalten Sie mit "declare -p" weder den Typ noch die ursprüngliche Variable.

Beispiel: 

$ 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"

Deshalb müssen Sie alle Referenzen durchlaufen. In bash-only würde das so aussehen: 

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
}

Mit dem obigen Beispiel:

$ vartype newtest
ARRAY

Um nach einem Array zu suchen, können Sie den Code ändern oder ihn mit grep verwenden: 

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

Ich habe mit Reubens guter Antwort oben angefangen. Ich habe ein paar Kommentare und einige meiner eigenen Verbesserungen umgesetzt und kam dazu:

#!/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
}

Jetzt kann ich das machen:

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