2014-01-20 3 views
12

Я знаю разницу в назначении между круглыми скобками () и фигурные скобки {}, когда grouping commands in bash.группы команд bash: для чего нужны фигурные скобки с точкой с запятой?

Но почему для фигурной фигурной скобки требуется точка с запятой после последней команды, тогда как для конструкции круглых скобок точка с запятой является необязательной?

 
$ while false; do (echo "Hello"; echo "Goodbye";); done 
$ while false; do (echo "Hello"; echo "Goodbye"); done 
$ while false; do { echo "Hello"; echo "Goodbye"; }; done 
$ while false; do { echo "Hello"; echo "Goodbye" }; done 
bash: syntax error near unexpected token `done' 
$ 

Я ищу информацию о том, почему это так. Я не ищу ответы, такие как ", потому что в документации сказано так:" или ", потому что он был спроектирован именно так". Я хотел бы знать почему он был спроектирован таким образом. Или, может быть, если это просто исторический артефакт?

Это можно наблюдать, по крайней мере, в следующих версиях :

  • ГНУ Баш, версия 3.00.15 (1) -release (x86_64-RedHat-Linux-гну)
  • ГНУ Баш, версия 3.2.48 (1) -release (x86_64-яблочно-darwin12)
  • GNU Баш, версия 4.2.25 (1) -release (x86_64-рс-Linux-гну)
+1

Для справки может быть полезно отметить версию bash, используемую во время тестирования. –

+0

@JonathonReinhart - версии были отмечены в вопросе - спасибо. –

+1

Как насчет «потому что это [как это задокументировано] (http://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping)». Четкое различие между скобками и круглыми скобками описано четко. –

ответ

18

Поскольку { и } только признанные в качестве специального синтаксиса, если они являются первым словом в команде.


Есть два важных пункта здесь, оба из которых находятся в definitions section руководства Баш. Во-первых, список метасимволов:

metacharacter

характер, что, когда в кавычки, отделяющей слова. Метасимволом является пустой или один из следующих символов: '|', '&', ';', '(', ')', '<', или '>'.

Этот список включает в себя круглые скобки, но не фигурные скобки (ни фигурных, ни квадрат). Обратите внимание, что это не полный список символов со специальным значением для оболочки, но это полный список символов, которые отдельных токенов. Таким образом, { и } не разделяют токены и будут считаться только самими токенами, если они смежны с метасимволом, например пробелом или точкой с запятой.

Хотя брекеты не метасимволы, они специально обрабатываются интерпретатором в parameter expansion (например. ${foo}) и brace expansion (например. foo.{c,h}). Кроме этого, они просто нормальные персонажи.Нет проблем с именованием файла {ab}, например, }{, так как эти слова не соответствуют синтаксису разложения параметров (для которого требуется $ до {) или расширение брекета (для которого требуется, по меньшей мере, одна запятая между { и }). В этом случае вы можете использовать { или } в качестве имени файла, без необходимости указывать символы. Аналогичным образом, вы можете вызвать файл if, done или time, не задумываясь о цитировании имени.

Эти последние лексемы "зарезервированные слова":

reserved word

Слово, которое имеет особое значение для оболочки. В большинстве зарезервированных слов вводятся конструкции управления потоком оболочки, такие как for и while.

Руководство баш не содержит полный список зарезервированных слов, что очень неудобно, но они, безусловно, включают в Posix отведенном:

! { } 
case do done elif else 
esac fi for if in 
then until while 

, а также расширения, реализованные на баш (и некоторых других оболочках):

[[ ]] 
function select time 

Эти слова не являются такими же, как встроенные модули (например, [), поскольку они фактически являются частью синтаксиса оболочки. Встроенные функции могут быть реализованы как функции или сценарии оболочки, но зарезервированные слова не могут быть вызваны тем, что они изменяют способ, которым оболочка анализирует командную строку.

Существует одна очень важная особенность зарезервированных слов, которые на самом деле не выделены в руководстве Баш, но сделан очень явно в Posix (из которого были взяты вышеприведенные списки зарезервированных слов, за исключением time):

Это признание [как зарезервированное слово] должно происходить только тогда, когда ни один из символов не указана, и когда слово используется как:

  • первое слово команды & hellip;

(Полный список мест, где зарезервированные слова признаются немного длиннее, но выше, является довольно хорошим резюме.) Другими словами, зарезервированные слова только защищены, когда они первым слово команда. И, поскольку { и } являются зарезервированными словами, они являются только специальным синтаксисом, если они являются первым словом в команде.

Пример:

ls } # } is not a reserved word. It is an argument to `ls` 
ls;} # } is a reserved word; `ls` has no arguments 

Там находится много больше, я мог бы написать о разборе оболочки, и Баш разборе, в частности, но она быстро становится утомительным.(Например, правило о том, когда # начинает комментарий и когда это обычный символ.) Примерное резюме: «не пытайтесь это дома»; действительно, единственное, что может анализировать команды оболочки, это оболочка. И не пытайтесь разобраться в этом: это всего лишь случайная коллекция произвольных выборов и исторических аномалий, многие, но не все, основанные на необходимости не нарушать старые сценарии оболочки с новыми функциями.

+1

Они явно особенны, поскольку OP обнаружил, может быть, вы могли бы расширить, почему они особенные, и что важно о * «если это первое слово в команде» *? – Kev

+0

@ Kev, как всегда, потому что дизайнеры так решили. Фактически, это позволяет вам писать 'echo {}' и печатать '{}'. – Ingo

+0

@rici +1 для точности и точности. – John1024