Чтобы быть в безопасности, я бы хотел, чтобы bash прервал выполнение скрипта, если он обнаружит синтаксическую ошибку.
К моему удивлению, я не могу этого достичь. ( set -e
недостаточно). Пример:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Результат (bash-3.2.39 или bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Ну, мы не можем проверять $?
после каждого оператора, чтобы перехватить синтаксические ошибки.
(Я ожидал такого безопасного поведения от разумного языка программирования ... возможно, об этом нужно сообщать как об ошибке / желании заразить разработчиков)
Больше экспериментов
if
не имеет значения.
Удаление if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Результат:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Возможно, это связано с упражнением 2 из http://mywiki.wooledge.org/BashFAQ/105 и связано с чем-то (( ))
. Но я считаю, что все еще нецелесообразно продолжать выполнять синтаксическую ошибку.
Нет, (( ))
не имеет значения!
Он ведет себя плохо даже без арифметического теста! Простой, простой скрипт:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Результат:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
источник
set -e
недостаточно, потому что ваша синтаксическая ошибка вif
утверждении. В любом другом месте следует прервать сценарий.set -e
не сработало. Но мой вопрос все еще имеет смысл. Можно ли отменить любую синтаксическую ошибку?Ответы:
Заключение целиком в функцию, похоже, помогает:
Результат:
Хотя я понятия не имею, почему - может быть, кто-то еще может объяснить?
источник
echo 'Bad2: has not aborted the execution after bad main!'
в качестве последнего к вашему примеру, и вывод: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: строка 6: #: синтаксическая ошибка: ожидаемый операнд ( маркер ошибки "#") Bad2: не прервал выполнение после плохого main! $Вы, вероятно, вводите в заблуждение относительно подлинного значения
set -e
. Внимательное прочтение результатовhelp set
шоу:Так
-e
о состоянии выхода из команд , являющихся ненулевой, а не о синтаксических ошибках в сценарии.В общем, это считается плохой практикой
set -e
, поскольку все ошибки (т. Е. Все ненулевые возвраты команд) должны быть аккуратно обработаны сценарием (подумайте надёжным сценарием, а не теми, которые выходят из строя после ввода имени файла с пространство или начинается с гипена).В зависимости от типа синтаксической ошибки, сценарий может даже не выполняться вообще. Я не достаточно разбираюсь в bash, чтобы точно сказать , какой класс синтаксических ошибок (если только они могут быть классифицированы) может привести к немедленному прерыванию работы скрипта или нет. Может быть, некоторые гуру Баш присоединятся и все прояснят.
Я только надеюсь, что разъяснил
set -e
заявление!О вашем желании:
Ответ определенно нет! поскольку то, что вы наблюдали (
set -e
не отвечает, как вы ожидаете), на самом деле очень хорошо задокументировано.источник
set -e
- это просто немного близко к моим целям, поэтому он упоминается и используется здесь. Мой вопрос не о томset -e
, а о безопасности bash, если он не может быть прерван из-за синтаксических ошибок. Я ищу способ сделать так, чтобы он всегда прерывался из-за синтаксических ошибок.Вы можете сделать скрипт сам по себе, поставив что-то вроде
в верхней части скрипта - после,
set -e
но перед любым значительным фрагментом кода.Я должен сказать, что это не очень хорошо, но если это работает для вас, возможно, это приемлемо.
источник
set -e
:bash -n "$0" || exit
Во-первых,
(( ))
in bash используется в качестве арифметических вычислений, а не в if ... используйте[]
для этого.Во-вторых,
${a[#]}
это странно, и именно поэтому выдает ошибки ...#
не имеет никакого значения массиваЯ не знаю, что вы хотите сделать с этим, но я предполагаю, что вы хотите знать количество полей, поэтому вы хотите
${#a[*]}
вместоНаконец, при сравнении целых чисел
-eq
рекомендуется использовать более==
(используется для строк). также==
будет работать, но-eq
рекомендуется.так ты хочешь:
источник
((
ключевое слово сif
ключевым словом. Например,if (( 5 * $b > 53 ))
. Если вы стремитесь к переносимости со старыми снарядами,[[
не является в целом предпочтительнее более[
.[[
и((
были разработаны специально как облегченные тесты, которые будут использоваться с «если» и т. Д. - в отличие от них[
, они никогда не порождают подпроцесс для оценки состояния.[
это встроенный Bash. Старые оболочки ожидают, что это будет его собственная программа.