Чому командній групі дужок потрібні пробіли після вступної дужки в Граматиці оболонки POSIX?


10

TL; DR : Чому для фіксованої групи POSIX потрібні пробіли після {зарезервованого слова, а нижня частина - після зарезервованого слова (?

Граматика оболонки POSIX визначає групу дужок і нижню частину, як описано нижче

brace_group      : Lbrace compound_list Rbrace

subshell         : '(' compound_list ')'

Тепер, якщо ми читаємо це буквально, пробіли значні. Це означатиме, що має бути простір, що розмежовує дужку та дужки, що розкривають, як і в

{ echo hello world; }

( echo hello world )

Це також відповідатиме визначенням складеної команди :

Кожна з цих складених команд має зарезервоване слово або оператор управління на початку, а відповідний термінатор - зарезервоване слово або оператор в кінці.

Однак те, що не має сенсу, полягає в тому, чому (list)і ( list )працювати просто чудово (цей простір після (не потрібно), проте розширення дужок повинно мати провідний простір, тобто {echo hello;}не буде працювати.

Зрозуміло, що зарезервоване слово, яке розглядається як слово оболонки, має сенс потребувати після цього пробілу для узгодження з поняттям розбиття поля , проте проміжки самі по собі не містять пробілів. Далі, якщо {і (обидва вважаються зарезервованими словами за визначенням POSIX складної команди, чому вони відносяться до символів пробілу після цих зарезервованих слів? Тепер у посібнику ksh (1) зазначено:

Слова, що є послідовностями символів, розмежовуються символами пробілу без процитів (пробіл, вкладка та новий рядок) або мета-символами (<,>, |,;, і, (і))

Іншими словами, має сенс, що ksh буде розпізнаватися (як роздільник слів, де перше слово буде командою або змінним призначенням. POSIX, однак, не згадується (як метасимвол. Єдине можливе пояснення, яке я виявив, що стосується граматики POSIX, це те, що {вважається "лексемою", де як (не вказано як одне.

/* These are reserved words, not operator tokens, and are
   recognized when reserved words are recognized. */


%token  Lbrace    Rbrace    Bang
/*      '{'       '}'       '!'   */

Отже, що могло б бути точним мотивом цієї розбіжності?

Примітки відповідей:

  • Переміщена прийнята галочка на відповідь Ісаака, оскільки вона забезпечує q уоте форму самого стандарту , який безпосередньо стосується мого питання:

    Наприклад, '(' і ')' є операторами управління, так що <space>в списку не потрібно. Однак '{' і '}' є зарезервованими словами у {list;}, так що в цьому випадку провідні <space>і <semicolon>обов'язкові.

  • Приймаючи відповідь Кусалананди . Відповідь Кусалананди стосується того, що мені потрібно, хоча переважно з неформальної та інтуїтивної точки зору; він вказує, що {це зарезервоване слово і (є оператором. Майкл Гомер також зазначив те саме в коментарях - що визначення Зведеного командування говорить (наголос додано):

    Кожна з цих складових команд має зарезервоване слово або оператор управління на початку

  • {визначаються як зарезервоване слово, схоже на forабо while, перелічене в Граматиці Shell (див. останній блок коду у питанні)

  • Розділ 2.9 констатує (додано наголос):

    Зокрема, подання включає проміжки між лексемами в тих місцях, де <blank>s не буде необхідним (коли один з лексем є оператором).

  • Хоча стандарт явно не визначає (як оператор, (його називають оператором; зокрема, йдеться в розділі 2.9.2

    Якщо конвеєр починається із зарезервованого слова! а command1 - це команда додаткової оболонки, програма повинна забезпечити (оператор на початку команди1 відокремлений від!! одним або декількома символами. Поведінка зарезервованого слова!

  • Питання про переповнення стека цифровою травмою вказує на розділ 2.4 "Зарезервовані слова":

    Це розпізнавання відбувається лише тоді, коли жоден із символів не цитується і коли слово використовується як:

    -Перше слово команди

  • Як згадується у відповіді Кусалаланда "Пробіли, показані в граматиці POSIX, - це не пробіли, які повинні бути там, у вхідних даних оболонки, а лише спосіб відображення самої граматики. Саме той факт, що дужки є зарезервованими словами, означає, що вони повинні бути оточені пробілом ". Як згадував Майкл Гомер у коментарях:" Якби простори самі по собі були значущими, їх потрібно було б перерахувати у виробництві "

Справа закрита.


3
Якщо простори самі були значущими, їх потрібно було б перерахувати у виробництві.
Майкл Гомер

2
"Далі, якщо {і (обидва вважаються зарезервованими словами за визначенням POSIX складної команди", пор. Msgstr "Кожна з цих складених команд на початку має зарезервоване слово або оператор управління ".
Майкл Гомер

2
@SergiyKolodyazhnyy Я вважаю, що він означає, що якби пробіл був значним, граматика повинна була б містити явний пробільний символ ( ' '). Натомість пробіли мають на увазі те, якими лексемами є слова.
Kusalananda

2
Визначення специфіки класу токенів ... найменше, незручно. Вся граматика є досить жахливою, і специфікація змішується, визначаючи речі в тексті прози (іноді неявно!), В прозових правилах, що передують граматиці, і в самій граматиці. Це зовсім незрозуміло, якщо ви вже не знаєте відповіді і працюєте назад. Усі лексичні правила визначаються назад, тим, що починається новий маркер, а не описується, що містить маркер. Це просто безлад навколо всіх.
Майкл Гомер

1
@ Сергій у формальній граматиці, виробництві (або виробничому правилі) описує, як можна генерувати щось із чогось іншого. Дивіться en.wikipedia.org/wiki/Production_%28computer_science%29 Отже command : simple_command | compound_command | compound_command redirect_list | function_definition ;, це виробництво, яке говорить про те, де ви можете мати команду, це може бути проста команда, складна команда або складна команда з перенаправленням, або визначення функції.
муру

Відповіді:


6

Це обмеження способу, яким оболонка розбиває лінії на лексеми.

Оболонка читає рядки з вхідного файлу, і відповідно до розділу 2 "Введення оболонки" перетворює їх у слово або оператор :

  1. Оболонка розбиває введення в лексеми: слова та оператори

{- це зарезервоване слово

Деякі слова - це зарезервовані слова

Зарезервовані слова - це слова, які мають особливе значення для оболонки. Наступними словами визнаються зарезервовані слова:

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

Слова, щоб їх можна було визнати словами, повинні бути розмежовані .

Зарезервовані слова розпізнаються лише тоді, коли вони обмежені ...

Переважно пробілами (точка 7) та операторами.

  1. Якщо поточний символ є без котировки <пробіл>, будь-який маркер, що містить попередній символ, обмежений, а поточний символ повинен бути відкинутий.

(є оператором

Оператори стоять самі :

тоді як оператори самі є розмежувачами.

Якщо "оператори" є :

3.260 Оператор

У мові командної оболонки або оператор управління, або оператор перенаправлення .

Операторами перенаправлення є :

Оператор перенаправлення

У мові командної оболонки маркер, який виконує функцію перенаправлення. Це один із наступних символів:

<     >     >|     <<     >>     <&     >&     <<-     <>

Операторами управління є :

3.113 Оператор управління

У мові командної оболонки маркер, який виконує керуючу функцію. Це один із наступних символів:

&   &&   (   )   ;   ;;   newline   |   ||

Висновок

Отже, '(' і ')' є операторами управління, тоді як '{' '}' є зарезервованими словами.

І точно такий же опис вашого питання знаходиться в специфікації :

Наприклад, '(' і ')' є операторами управління, так що <пробіл> не потрібен (список). Однак '{' і '}' є зарезервованими словами у {list;}, так що в цьому випадку потрібні провідні <space> і <semicolon>.

Що саме пояснює, чому після a потрібно пробіл (або якийсь інший роздільник) {.

Це дійсно:

{ echo yes;}

Як це:

{(echo yes);}

Це:

{(echo yes)}

Або навіть це:

{>/dev/tty echo yes;}

Ну, остання цитата саме на місці! + 1'ed. Мені потрібно переглянути питання та відповіді зараз
Сергій Колодяжний,

13

Різниця між фігурними дужками і дужками в тому , що фігурні дужки (і !) є зарезервованими словами, так само , як for, if, і thenт.д. , а Дужки оператори управління. Слова потрібно розділити пробілом.

Це означає, що так само, як і у вас, не може бути

foriin*; do

ви не можете мати

{somecommand;} >file

або

if !somecommand; then

Пробіли, показані в граматиці POSIX - це не пробіли, які повинні бути там, у вхідних даних оболонки, а лише спосіб відображення самої граматики. Справа в тому, що дужки є зарезервованими словами, що означає, що вони повинні бути оточені пробілом, тоді як в дужках підзаголовок немає.


1
Ну, це, схоже, відповідає на це, і я бачу, що він говорить, "Зокрема, представлення включають проміжки між лексемами в тих місцях, де <blank> s не буде необхідним (коли один з жетонів є оператором)". Лише одне питання: де стандарт визначається (як оператор? Принаймні, це не в розділі граматики
Сергій Колодяжний,

@MichaelHomer Ах, "оператор управління", так само ;. Дякую за це.
Kusalananda

Оператори управління вказані вгорі основної сторінки в розділі ВИЗНАЧЕННЯ. Ми можемо розглядати ()як операторів управління, як |у тому, що обидва включають доподібні. І { }працює в поточній оболонці і не може залучати нижню частину оболонки.
glenn jackman

@Kusalananda Виявив це, розділ 2.9.2: "Якщо конвеєр починається із зарезервованого слова !, а command1 - це команда додаткової оболонки, додаток повинен гарантувати, що (оператор на початку команди1 відокремлений від!! Одним або декількома < blank> символи. Поведінка зарезервованого слова! негайно слідує (оператор не вказаний. "Не чітке визначення, але стандарт називає його (оператором
Сергій Колодяжний,

@glennjackman Хоча це правда, що трубопроводи включають підрозділи, це не той тип визначення, який видається відповідним. Стандарт також зазначає, що в деяких реалізаціях добре, щоб конвеєр працював у поточному середовищі виконання оболонки (і я знаю, що це в стандарті, тому що я бачив текст вчора і шукаю його зараз). Однак ваша пропозиція вказує на мене, щоб знайти цитату, яку я прокоментував вище, де, як мінімум, стандарт називає його оператором, хоча чітко не визначає його як один
Сергій Колодяжний,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.