почему в выражении "if" "then" должно быть в следующей строке в bash?
if
следует then
в bash, но я не понимаю, почему then
нельзя использовать в одной строке, например if [...] then
его нужно использовать в следующей строке. Устраняет ли это некоторую двусмысленность кода? или bash так устроен? какова основная причина этого?
Я пытался написать if
а также then
в той же строке, но выдает следующую ошибку:
./test: line 6: syntax error near unexpected token \`fi'
./test: line 6: \`fi'
код:
#!/bin/bash
if [ $1 -gt 0 ] then
echo "$1 is positive"
fi
4 ответа
Ему должен предшествовать разделитель некоторого описания, не обязательно в следующей строке (а). Другими словами, чтобы добиться желаемого, вы можете просто использовать:
if [[ $1 -gt 0 ]] ; then
echo "$1 is positive"
fi
Кроме того, для подобных однострочных я предпочитаю:
[[ $1 -gt 0 ]] && echo "$1 is positive"
Но это просто потому, что я предпочитаю видеть на экране как можно больше кода. На самом деле это просто стиль, который можно игнорировать.
(а) Причину этого можно найти вBash
manpage (выделено мной):
Зарезервированные слова: зарезервированные слова - это слова, которые имеют особое значение для оболочки. Следующие слова распознаются как зарезервированные, если они не заключены в кавычки и являются либо первым словом простой команды (см. ГРАММАТУРА ОБОЛОЧКИ ниже), либо третьим словом команды
case
илиfor
команда:
! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]
Обратите внимание, что, хотя в этом разделе говорится, что это "первое слово простой команды", кажется, что справочная страница противоречит сама себе в указанном SHELL GRAMMAR
раздел:
Простая команда - это последовательность необязательных назначений переменных, за которыми следуют слова, разделенные пробелами, и перенаправления, которые завершаются управляющим оператором. Первое слово определяет команду, которая должна быть выполнена, и передается как нулевой аргумент.
Итак, считаете ли вы его часть следующей команды или разделителя какой - то спорно. Что не оспаривается, так это то, что ему нужен какой-то разделитель (например, новая строка или точка с запятой) передthen
ключевое слово.
На странице руководства не объясняется, почему она была разработана таким образом, но она, вероятно, упрощает синтаксический анализ команд.
Вот еще один способ объяснить необходимость переноса строки или точки с запятой перед then
: то, что находится между if
а также then
это команда (или последовательность команд); еслиthen
просто идет сразу после команды без разделителя, было бы неоднозначно, следует ли рассматривать ее как ключевое слово оболочки или просто аргумент команды.
Например, это вполне допустимая команда:
echo This prints a phrase ending with then
... который печатает "Это печатает фразу, оканчивающуюся на then". Теперь рассмотрим вот это:
if echo This prints a phrase ending with then
если вы напечатаете "Это напечатает фразу, оканчивающуюся на then", и найдите then
ключевое слово позже, или следует просто напечатать "Это печатает фразу, заканчивающуюся на" и обработать then
как ключевое слово?
Чтобы разрешить эту двусмысленность, синтаксис оболочки говорит, что он должен рассматривать "then" как аргумент для echo
, и для того, чтобы обрабатывать его как ключевое слово, вам нужен разделитель команд (разрыв строки или точка с запятой), чтобы отметить конец команды.
Теперь вы можете подумать, что ваш if
состояние [ $1 -gt 0 ]
, уже имеет отличный разделитель, а именно ]
. Но в синтаксисе оболочки это просто аргумент[
команда (да, это команда). Попробуйте эту команду:
[ 1 -gt 0 ] then
... и вы, вероятно, получите ошибку типа "-bash: [: missing ']'", потому что [
Команда проверила свой последний аргумент, чтобы убедиться, что это был "]", обнаружила, что это было "тогда", и запаниковала.
Возможно, это поможет понять, почему это так, на нескольких примерах. Аргумент кif
это последовательность команд; так что вы можете сказать например
if read -r -p "What is your name?" name
[ "$name" -eq "tripleee" ]
then
echo "I kneel before thee"
fi
или даже сложное соединение, подобное
while read -r -p "Favorite number?" number
case $number in
42) true; break;;
*) false;;
esac
do
echo "Review your preferences, then try again"
done
Эта чрезвычайно мощная, но потенциально сбивающая с толку функция оболочки, вероятно, является одной из ее наиболее неправильно понимаемых конструкций. Возможность передавать последовательность команд в операторы управления потоком может сделать очень элегантные сценарии, но часто полностью упускается (см., Например, почему тестирование "$?" Для проверки успешности команды или нет, анти-шаблон?)
Если это поможет, вы можете использовать точку с запятой.
if [ $1 -gt 0 ]; then
echo "$1 is positive"
fi
# or even
if [ $1 -gt 0 ]; then echo "$1 is positive"; fi
Что касается того, почему, это помогает мне думать оif
, then
, else
, а также fi
как команды bash и, как и все другие команды, они должны быть в начале строки (или после точки с запятой).