Подтвердить что ты не робот

В чем причина странного синтаксиса оператора case для bash/zsh script?

Взглянув с точки зрения программиста, оболочка script - это еще один язык программирования, где нужно учиться и соответствовать правилам языка. Тем не менее, я должен признать, что этот синтаксис - самый странный стиль, который я когда-либо видел на довольно часто используемом языке. Оболочка взяла этот синтаксис из более старого языка, из которого он сходит? Есть ли специальный синтаксис/смысл в синтаксисе?

В качестве примера, вот небольшой фрагмент, который я беру из другого сообщения в SO

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        check_status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

Посмотрев на это, во-первых, я вижу, что case заканчивается на esac, что является его обратным форматом (например, if, заканчивающимся на fi). Во-вторых, я понимаю, что за каждым случаем следует ). Достаточно справедливо, но почему мне нужно два ; в конце каждого утверждения? Я бы также сказал, что ) без сопровождающего ( уродливый.

Я ищу дополнительную информацию об историческом аспекте языка, но я также открыт по техническим причинам.

4b9b3361

Ответ 1

По запросу:

  • Так вы можете догадаться, почему цикл "for ...; do ...; done", а не "for ...; do ...; od"? Для этого была веская причина - но ключевое слово с обратным обращением, подобным Алголу, для обозначения конца было использовано в другом месте.

Ответ:

  • Синтаксис был получен от Bourne (от славы раковины Bourne). Он работал над Algol, и ему понравилось достаточно, чтобы смоделировать синтаксис оболочки на Algol. Алгол использует обратные ключевые слова, чтобы отметить концы конструкций, поэтому "case... esac" был подходящим. Причина, по которой циклы не заканчиваются на "od", заключается в том, что в Unix-восьмеричном дампе уже была команда "od". Итак, вместо этого используется "done".

По репутации исходный код оболочки Bourne был написан на идиосинкразическом C с макросами, чтобы он выглядел как Algol. Это затрудняло поддержание.

В отношении основного вопроса - о том, почему не существует открытой скобки (скобки) вокруг альтернатив в выражении case - у меня есть пара связанных теорий.

Прежде всего, когда была написана оболочка Борна (конец 1970-х годов), многое редактировалось с помощью ed, стандартный текстовый редактор. Он не имеет понятия о переходе к сбалансированной круглой скобке или других таких обозначениях, поэтому не было требования для ведущей круглой скобки. Кроме того, если вы пишете документ, вы вполне можете маршалировать свои аргументы с помощью:

a) ...blah...
b) ...more...
c) ...again...

Открывающая скобка часто опускается - и оператор case подходит к этой модели довольно счастливо.

Конечно, с тех пор мы привыкли к редакторам, которые отмечают совпадающие открытые круглые скобки при вводе закрывающей круглой скобки, поэтому старая нотация оболочки Bourne является досадой. Стандарт POSIX делает ведущие скобки необязательными; наиболее современные реализации POSIX-подобных оболочек (Korn, Bash, Zsh) будут поддерживать это, и я обычно использую его, когда мне не нужно беспокоиться о переносимости на такие машины, как Solaris 10, где /bin/sh все еще является верная оболочка Борна, которая не позволяет вести круглые скобки. (Обычно я занимаюсь этим, используя #!/bin/ksh как shebang.)

Ответ 2

Причиной использования ;; является то, что один ; может использоваться для записи нескольких операторов в одной строке, например:

restart)
   stop; start;;
...

Ответ 3

Bash может принимать совпадающие скобки:

case "$1" in
    (start)
        start
        ;;
    (stop)
        stop
        ;;

    etc.

Ответ 4

Закрывающая скобка иногда используется в списках на естественном языке, например

1) do this
2) do that

Обратные ключевые слова были взяты из какой-то формы Алгола, но на самом деле это очень хорошая идея для интерактивного использования. Они четко разделяют конец конструкции, в том числе if/else.

Например, с синтаксисом типа C, после этого был проанализирован:

if (condition)
    command here;

есть ли else или нет? rc, оболочка из Plan 9 с более синтаксисом C-типа, решает это, предоставляя if not вместо else, но это не так.

С синтаксисом оболочки Bourne у вас будет либо else, либо fi, и нет необходимости читать дополнительный ввод.