Для версій 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, але оператор для умовних виразів.