В чем причина странного синтаксиса оператора case в скрипте bash / zsh? - PullRequest
43 голосов
/ 21 ноября 2010

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

В качестве примера, вот небольшой фрагмент, который я взял из другого поста на 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). Во-вторых, я понимаю, что за каждым случаем следует ). Справедливо, но зачем мне два ; в конце каждого утверждения? Я бы также сказал, что ) без сопровождающего ( ужасен.

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

Ответы [ 4 ]

37 голосов
/ 22 ноября 2010

За запрос:

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

Ответ:

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

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

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

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

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

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

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

24 голосов
/ 21 ноября 2010

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

restart)
   stop; start;;
...
11 голосов
/ 21 ноября 2010

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

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

    etc.
3 голосов
/ 22 ноября 2010

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

1) do this
2) do that

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

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

if (condition)
    command here;

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

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

...