установить -u использование не работает, как ожидалось

12

Я учусь тому, как эффективно использовать различные setопции в моем скрипте, и наткнулся на set -uто, что кажется идеальным для выхода из моего скрипта, если переменная не установлена ​​должным образом (например, удаление пользователей). Согласно справочной странице, set -uи set -eделает следующее ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

Я создал тестовый скрипт для проверки этой функциональности, но он не работает должным образом. Возможно, кто-то мог бы лучше объяснить мою проблему мне и где я неправильно интерпретирую? Тестовый скрипт ниже. Спасибо.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

Я ожидаю, что скрипт отобразит 0 и «Это работает» , а затем потерпит неудачу, так как ${testing2}не установлен.

Вместо этого у меня отображается 0 и «Это работает» , затем 0 и затем 0 Это не должно появляться

Кто-нибудь может дать некоторые знания? Спасибо.

Azifor
источник
1
Итак, продолжение ... Есть ли способ сделать недопустимой установку переменной в нулевую строку / вызвать ошибку? Я думаю, нет.
Люк Дэвис

Ответы:

10

Из "Человек Баш":

Параметр устанавливается, если ему было присвоено значение. Нулевая строка является допустимым значением. Как только переменная установлена, она может быть сброшена только с помощью встроенной команды unset.

Когда вы это делаете, testing2=вы устанавливаете переменную в нулевую строку.

Измените это на unset testing2и попробуйте снова.


set -eНе помогает в этом случае назначение не имеет код выхода 1. Попробуйте это , чтобы увидеть , что последняя команда выполняется (присвоение) имеет код завершения 0, или прочитать этот вопрос :

$ false; a=""; echo $?
0

И я также считаю, что использование set -e - это скорее проблема, чем решение.

Что может привести к ошибке при использовании неустановленных переменных set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Будет выводить:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable
Сообщество
источник
3

testing2=устанавливает testing2переменную в пустую строку; переменная на самом деле установлена .

Однако, если бы вы работали echo $testing99в интерактивной оболочке Bash (без настройки errexit, т. Е. set -e), Вы получите ошибку:

bash: testing99: unbound variable

В сторону

Во время тестирования сценариев я обнаружил, что интерактивная оболочка не всегда завершается при попытке развернуть переменную, которая не была установлена, в то время как неинтерактивная оболочка (запускающая сценарий оболочки) всегда завершается . Согласно справочной странице POSIX для set:

-u Оболочка должна написать сообщение для стандартной ошибки, когда она пытается раскрыть переменную, которая не установлена, и немедленно завершить работу. Интерактивная оболочка не должна выходить.

Интерактивное Bash оболочки не будет выходить , если errexitне имеет также установлен. С другой стороны, интерактивная панель инструментов не выйдет, даже если set -eона уже была запущена.

Энтони Геогеган
источник
Если тире не выходит с set -e; set -u; unset aa; эхо $ аа, то черта не так.
Шили
@schily Когда я впервые заметил это, я подумал, что авторы черточки знают лучше меня и что в спецификациях POSIX могла быть некоторая двусмысленность, но перепроверив pubs.opengroup.org/onlinepubs/9699919799/utilities/… , я согласен, это похоже на ошибку, хорошо.
Энтони Геогеган
Есть простое правило: когда и Korn Shell, и Bourne Shell соглашаются, а другая реализация оболочки имеет отклонение, тогда другая оболочка ведет себя некорректно.
Шили