В тесте Bash, если ассоциативный массив объявлен

Как я могу проверить, объявлен ли ассоциативный массив в Bash? Я могу проверить переменную как:

[ -z $FOO ] && echo nope

но я не работаю с ассоциативными массивами:

$unset FOO
$declare -A FOO
$[ -z $FOO ] && echo nope
nope
$FOO=([1]=foo)
$ [ -z $FOO ] && echo nope
nope
$ echo ${FOO[@]}
foo

РЕДАКТИРОВАТЬ:

Спасибо за ваши ответы, оба, кажется, работают, поэтому я позволю скорости решить:

$ cat test1.sh
#!/bin/bash
for i in {1..100000}; do
    size=${#array[@]}
    [ "$size" -lt 1 ] && :
done
$ time bash test1.sh #best of five

real    0m1.377s
user    0m1.357s
sys     0m0.020s

и другие:

$ cat test2.sh
#!/bin/bash

for i in {1..100000}; do
    declare -p FOO >/dev/null 2>&1 && :
done
$ time bash test2.sh #again, the best of five

real    0m2.214s
user    0m1.587s
sys     0m0.617s

РЕДАКТИРОВАТЬ 2:

Давайте быстро сравним решение Chepner с предыдущими:

#!/bin/bash

for i in {1..100000}; do
    [[ -v FOO[@] ]] && :
done
$ time bash test3.sh #again, the best of five

real    0m0.409s
user    0m0.383s
sys     0m0.023s

Ну, это было быстро.

Еще раз спасибо, ребята.

4 ответа

Решение

В bash 4.2 или позже, вы можете использовать -v опция:

[[ -v FOO[@] ]] && echo "FOO set"

Обратите внимание, что в любой версии, используя

declare -A FOO

на самом деле не создает ассоциативный массив сразу; он просто устанавливает атрибут на имя FOO который позволяет назначить имя в виде ассоциативного массива. Сам массив не существует до первого присваивания.

Ты можешь использовать declare -p проверить, была ли объявлена ​​переменная:

declare -p FOO >/dev/null 2>&1 && echo "exists" || echo "nope"

И проверить конкретно ассоциативный массив:

[[ "$(declare -p FOO 2>/dev/null)" == "declare -A"* ]] &&
   echo "array exists" || echo "nope"

Это версия Community Wiki из отличный ответ на user15483624 на вопрос , который в настоящее время закрыт в двух экземплярах. Если этот пользователь решит добавить здесь свой собственный ответ, его следует удалить в пользу ответа с его именем.


Предыдущие ответы на этот вопрос следует использовать только тогда, когда требуется совместимость с bash 4.x и более ранними версиями. В bash 5.0 и более поздних версиях расширение для проверки типа переменной доступно напрямую; его использование намного эффективнее, чем анализ вывода declare -p, а также позволяет избежать некоторых непреднамеренных побочных эффектов других предложений.

Следующее можно использовать, чтобы проверить, является ли переменная bash ассоциативным массивом.

      [[ ${x@a} = A ]]

${x@a} может использоваться для проверки того, является ли это переменной или массивом.

      $ declare x; echo "${x@a}"

$ declare -a y; echo "${y@a}"
a
$ declare -A z; echo "${z@a}"
A

Один из самых простых способов - проверить размер массива:

size=${#array[@]}
[ "$size" -lt 1 ] && echo "array is empty or undeclared"

Вы можете легко проверить это в командной строке:

$ declare -A ar=( [key1]=val1 [key2]=val2 ); echo "szar: ${#ar[@]}"
szar: 2

Этот метод позволяет вам проверить, объявлен ли массив и является ли он пустым или необъявленным вообще. И пустой массив и необъявленный массив вернут 0 размер.

Другие вопросы по тегам