2014-11-14 3 views
5

Как проверить, объявлен ли ассоциативный массив в 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 

EDIT:

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

$ 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 

EDIT 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 

Хорошо это было быстро.

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

ответ

5

bash В 4.2 или более поздней версии, вы можете использовать -v вариант:

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

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

declare -A FOO 

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

+0

Я до сих пор не смог найти случай, когда «FOO [@]» в приведенном выше коде может произвести любой другой результат, чем просто «FOO». Если целью было также обнаружить, что FOO не является массивом, я не знаю ни одного решения, которое не требует использования 'declare' (приведенная ниже проверка размера массива не помогает). –

+0

Я думаю, что новый достаточно баш мог бы избежать 'declare', используя' $ {FOO @ A} ', чтобы получить ту же информацию о' FOO'. –

7

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

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

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

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

Вы не можете использовать declare -p, чтобы проверить, объявлена ​​ли переменная, если переменная не была установлена. – Jani

+1

@ Джани не уверен, что вы заявляете. Объявление будет возвращать ненулевой статус выхода (в отличие от команды 'help'), если переменная не была установлена. Во втором примере у @anubhava есть опечатка (должно быть, '2>/dev/null' я думаю).В противном случае это, по-видимому, единственный функциональный ответ, если вы хотите определить, было ли имя объявлено как ассоциативный массив. –

+0

@RonBurk: Спасибо за ваш комментарий. '>/dev/null 2> & 1' перенаправляет как stdout, так и stderr на'/dev/null', поэтому мы можем работать только с кодом выхода. – anubhava

2

Один из самых простых способов является чеке размер массив:

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

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

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

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