Почему ;
после do
цикла в оболочке не появляется символ после одной строки?
Вот что я имею в виду. Когда написано в несколько строк, for
цикл выглядит так:
$ for i in $(jot 2)
> do
> echo $i
> done
И в единственной строке:
$ for i in $(jot 2); do echo $i; done
Все рухнувшие линии получить ;
после них , за исключением для do
линии, и если включать ;
, это ошибка. Кто-то, вероятно, чертовски умнее меня, решил, что это правильно делать по какой-то причине, но я не могу понять, в чем причина. Это кажется мне противоречивым.
То же самое с while
петлями тоже.
$ while something
> do
> anotherthing
> done
$ while something; do anotherthing; done
while
/for
либо.Ответы:
Это синтаксис команды. Смотрите составные команды
Обратите особое внимание:
do commands
Большинство людей ставят
do
иcommands
в отдельной строке, чтобы облегчить чтение, но это не обязательно, вы можете написать:Я знаю, что этот вопрос конкретно о оболочке, и я связан с руководством по bash. Так не написано в руководстве по оболочке, но так написано в статье, написанной Стивеном Борном для журнала байтов.
Стивен говорит:
источник
for i in thing; do; something; done
. Хотя допускается разрыв строки, точка с запятой не допускается.something
предмет иdo
относится к нему. Так же, как в английской структуре предложений.while
синтаксисе), поэтому вам нужно что-то отличить команды условия от команд тела цикла. Использованиеdo
для их разделения, вероятно, то, что казалось наиболее подходящим.Я не знаю, какова первоначальная причина этого синтаксиса, но давайте рассмотрим тот факт, что
while
циклы могут принимать несколько команд в разделе условий, напримерЗдесь
do
ключевое слово необходимо, чтобы отделить раздел условия от основной части цикла.do
является ключевым словом, подобнымwhile
,if
иthen
(иdone
), и кажется, что оно соответствует другим, что для него не требуется точка с запятой или символ новой строки после него, но оно появляется непосредственно перед командой.Альтернатива (обобщенная к
if
иwhile
) будет выглядеть несколько уродливо, нам нужно написать, например,Синтаксис
for
циклов просто похож.источник
Синтаксис оболочки основан на префиксах. В нем есть пункты, введенные специальными ключевыми словами. Некоторые пункты должны идти вместе.
while
Петля сделана из одного или более команд тестирования:и одной или несколькими командами тела:
Что-то должно сказать оболочке, что цикл while начинается. Это цель
while
слова:Но тогда, вещи неоднозначны. Какая команда является началом тела? Что-то должно указывать на это, и вот что
do
делает префикс:и, наконец, что-то должно указывать на то, что последнее тело было замечено; специальное ключевое слово
done
делает это.Эти ключевые слова оболочки не требуют разделения точки с запятой даже на одной строке. Например, если вы закроете несколько вложенных циклов, вы можете просто иметь
done done done ...
.Скорее точка с запятой находится между,
... test ; body ...
если они находятся на одной строке. Эта точка с запятой понимается как терминатор: она принадлежитtest
. Поэтому, еслиdo
ключевое слово вставлено между ними, оно должно быть между точкой с запятой иbody
. Если бы он был на другой стороне точки с запятой, он был бы неправильно встроен вtest
синтаксис команды, а не помещен между командами.Синтаксис оболочки был первоначально разработан Стивеном Борном и вдохновлен Алголом . Борн настолько любил Algol, что использовал множество макросов C в исходном коде оболочки, чтобы C выглядел как Algol. Вы можете просмотреть источники оболочки 1979 года из Версии 7 Unix . Макросы находятся внутри
mac.h
, и они используются повсеместно. Напримерif
заявления предоставляются в качествеIF
...ELSE
...ELIF
...FI
.источник
Я бы сказал, что
do
здесь нет ничего особенного. Вы получаете ошибку, потому что;
не можете запустить список команд. Если это так, первая команда будет пустой, а грамматика не разрешает пустые команды (присваивание переменных или перенаправление без команды, да, но абсолютно ничего, нет). Это верно в любом количестве мест, где ожидается список команд:Четное:
Во всех этих местах ожидается список команд, поэтому ведение
;
является неожиданным.источник
do
(иif
т.д.), хотя?Синтаксис:
Любой символ новой строки, либо в списке команд, либо перед «do» или «done» может быть заменен на «;».
Новая строка (но не «;») разрешается после «do» и перед «in», только для того, чтобы все выглядело лучше, но не было бы смысла требовать новой строки там.
источник
if
аналогично с его ключевыми словами: это вполне читабельно, когда команды короткие:источник
\n
после того,do
как все это имело смысл (до тех пор, пока вы не думаете о невозможности вставить произвольное\n
между другими командами и аргументами).do
,then
,else
не арг - если бы они были, вы бы не позволили использовать точку с запятой перед ними. Это ключевые слова оболочки (см.type if then elif else fi
)Короткий ответ, потому что это определяется грамматикой оболочки POSIX . Все, что находится между
do
иdone
считается группой операторов, в то время как;
является последовательным разделителем:Кроме того, если
;
необходимы стандарт будет явно указать , так и будет включать в себяsequential_sep
послеDo
.источник
Потому что do - это ключевое слово, а то, что следует, по сути являются параметрами. Интерпретатор Bash знает, что еще следует. Это похоже на то, как нет ';' после я в для команды. Вы можете добавить новую строку после i в for и набрать остальное в новой строке, и она будет работать нормально.
источник