Для версій Bash до "GNU bash, версія 4.2" чи є еквівалентні альтернативи для -v
параметра test
команди? Наприклад:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
Для версій Bash до "GNU bash, версія 4.2" чи є еквівалентні альтернативи для -v
параметра test
команди? Наприклад:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
Відповіді:
Переноситься на всі оболонки POSIX:
if [ -n "${foobar+1}" ]; then
echo "foobar is defined"
else
echo "foobar is not defined"
fi
Зробіть це, ${foobar:+1}
якщо ви хочете поводитись foobar
так само, будь то порожній чи не визначений. Ви також ${foobar-}
можете отримати порожній рядок, коли він foobar
не визначений, а значення foobar
іншим чином (або поставити будь-яке інше значення за замовчуванням після -
).
У ksh, якщо foobar
оголошено, але не визначено, як у typeset -a foobar
, то ${foobar+1}
розширюється на порожній рядок.
Zsh не має змінних, які оголошуються, але не встановлюються: typeset -a foobar
створює порожній масив.
У bash масиви поводяться по-різному і дивно. ${a+1}
тільки розширюється, 1
якщо a
це не порожній масив, наприклад ,
typeset -a a; echo ${a+1} # prints nothing
e=(); echo ${e+1} # prints nothing!
f=(''); echo ${f+1} # prints 1
Цей же принцип застосовується і до асоціативних масивів: змінні масиву трактуються так, як визначено, якщо вони мають не порожній набір індексів.
Інший, специфічний для bash спосіб тестування того, чи була визначена будь-яка змінна будь-якого типу, - це перевірити, чи є вона в списку . Це звітує про порожні масиви, як визначено, на відміну від них , але звітує про оголошені, але непризначені змінні (${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
) як невизначені.
case " ${!foobar*} " in
*" foobar "*) echo "foobar is defined";;
*) echo "foobar is not defined";;
esac
Це еквівалентно тестуванню повернутого значення typeset -p foobar
абоdeclare -p foobar
, за винятком того, що typeset -p foobar
не вдається на оголошених, але непризначених змінних.
У bash, як у ksh, set -o nounset; typeset -a foobar; echo $foobar
запускається помилка при спробі розширення невизначеної змінної foobar
. На відміну від ksh, set -o nounset; foobar=(); echo $foobar
(або echo "${foobar[@]}"
) також викликає помилку.
Зауважте, що в усіх описаних тут ситуаціях ${foobar+1}
розширюється на порожній рядок, якщо і лише тоді, якщо $foobar
це призведе до помилки під set -o nounset
.
echo "${foobar:+1}"
не друкується, 1
якщо declare -a foobar
раніше було видано, і таким чином foobar
є індексованим масивом. declare -p foobar
правильно звітує declare -a foobar='()'
. Чи "${foobar:+1}"
працює лише для змінних без масиву?
${foobar+1}
(без того :
, я перевернув два приклади в моїй оригінальній відповіді) є правильним для масивів у bash, якщо ваше визначення "визначеного" є "буде $foobar
працювати під set -o nounset
". Якщо ваше визначення інше, баш трохи дивний. Дивіться мою оновлену відповідь.
0
індекс, ні ключ не визначені так, як це правда a=()
, ${a+1}
правильно нічого не повертає.
defined
оператор. Test
міг би це зробити; вона не може бути важко ( гм ....)
Підводячи підсумки відповіді Жиля, я склав свої наступні правила:
[[ -v foobar ]]
для змінних у версії Bash> = 4.2.declare -p foobar &>/dev/null
для змінних масивів у версії Bash <4.2.(( ${foo[0]+1} ))
або (( ${bar[foo]+1} ))
для підписок індексованих ( -a
) та keyed ( -A
) масивів ( declare
) відповідно. Тут не працюють варіанти 1 і 2.Я використовую однакову техніку для всіх змінних у bash, і вона працює, наприклад:
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
Виходи:
foobar is unset
в той час як
foobar=( "val" "val2" )
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
Виходи:
foobar is set
foobar=""
повідомлять про це foobar is unset
. Не чекайте, я повертаю це назад. Дійсно тестує лише, чи перший елемент порожній чи ні, тому здається, що це лише гарна ідея, якщо ви знаєте, що змінна НЕ є масивом, і вас цікавить лише порожнеча, а не визначеність.
-v
не варіант дляtest
, але оператор для умовних виразів.