Чому послідовність має значення у виконанні цих команд bash?


10

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

Якщо я виконую:

ls;date;time

результати трьох запитів відображаються послідовно.

Однак при зміні позиції дати та часу з’являється повідомлення про помилку.

Тож якщо я виконую:

ls;time;date

повідомлення про помилку говорить: bash: syntax error near unexpected token 'date'.

Хтось може це пояснити?


Ваша проблема лежить на time;dateпроти date;time. Це, мабуть, є проблемою з конвеєром bashі останнім символом, що генерується з timeрезультатом. Тестовані результати в різних емуляторах терміналів: - [Bash] $ date; час # [OK] $ time; дата # [ NotOK ] bash: помилка синтаксису біля несподіваного маркера `date '$ time #, лише помилка не здається, що це результат будь-якої дати. - [Csh] $ date; час # [OK] $ time; дата # [OK] - [Tcsh] $ date; час # [OK] $ time; дата # [OK] - [Ksh] $ date; час # [ ОК] $ time; дата № [ОК]
Мостафа Шахверді

Я оновив свою відповідь, пояснивши повідомлення про помилку. Перевірте, чи це відповідь, яку ви шукали.
zwets

Відповіді:


10

timeКоманда в вашому трубопроводів не /usr/bin/timeдвійкова, але Баш timeвбудовані. Порівняйте man timeз help time. Виявлена ​​помилка - це баш не в змозі аналізу timeаргументу. Це повинно бути або присутнім, або бути новим рядком. Це новий рядок у вашому першому прикладі, але відсутній у другому.

З іншого боку, якби ти бігав

ls;date;'time'

або

ls;'time';date

де лапки навколо 'time'відкликають його статус як зарезервоване слово, то bash не має проблем з розбором рядка. Тепер він аналізує три команди в списку, які він буде виконувати послідовно, і /usr/bin/timeповідомляє про помилку використання в будь-якому випадку.

Додаток

Було помічено, що хоч і time ; dateприносить помилку, але time ; ; dateце не так. Ймовірне пояснення полягає в тому, що time ;інтерпретується bash як рівнозначне time <newline>. Потім вираз time ; ; dateаналізується як список time ;та date.

Це узгоджується із зауваженням, яке є time ;і time ; ;легальним, другий розбирається як список однотонних, що містить time ;слідом необов'язковий крапку з комою, дозволену після списків.

Отже, інший спосіб пояснити, чому time ; dateвиникає помилка, bash: syntax error near unexpected token 'date'- це те, що timeспоживає крапку з комою, відокремлюючи її date. Це можна зробити тільки тому, що timeце зарезервоване слово.


Дякую за гарне пояснення! Але потім така поведінка мені схожа на помилку: timeповинна дозволити команду NULL, а крапкою з комою слід розмежувати списки, тому timeкоманда IMO не повинна "споживати" крапку з комою після неї. Інші вбудовані команди (які можуть брати аргументи) не проявляють подібної поведінки.
влаштовуйте

@arrange Ускладнення полягає в тому, що час не дозволяє нульовій команді (що б все розігнало), вона дозволяє лише новий рядок замість команди. Так time;dateсправді синтаксично неправильно в будь-якій інтерпретації. Однак time ; і time ; ;тоді це було б також незаконно. Можна обговорити, чи timeє поведінка помилкою чи просто недокументованою (вона є внутрішньо послідовною), але повідомлення про помилки, безумовно, існує. Чи готові ви подати його?
zwets

Ну, я подивився на джерело (bash4.2: parse.y: рядки 1205-1221) і там воно говорить, що time by itself can time a null commandпотім це робиться мимо $$ = make_simple_command (x, (COMMAND *)NULL);. Щодо подання помилки, я не впевнений 8)
домовтеся

Слід зазначити, що це питання є специфічним для удару. Виконання time ; dateробіт в ksh93і mkshбез будь - яких помилок, навіть якщо в ksh є timeключове слово.
Сергій Колодяжний

2

Bash розглядає вбудований модуль timeяк особливий випадок при аналізі командних рядків.

Як можна прочитати на сторінці bash, введений рядок спочатку розбивається на список:

pipeline ; pipeline

де трубопровід:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

або в нашому випадку просто:

time command

тобто якщо час присутній, тоді також повинна бути присутня команда .

[Існує особливий випадок, який дозволяє timeслідувати новим рядком, але це не стосується тут]

Отже, у нашому випадку ми маємо:

time;date

розділяється на два трубопроводи:

1. time
2. date

і трубопровід 1 недостатньо сформований, оскільки ми маємо timeбез команди. Звідси помилка.

Зауважте, що і командний рядок timeтут не працює:

$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]

bash розбирає це, як очікувалося, на 2 трубопроводи:

1. /usr/bin/time
2. date

а /usr/bin/timeпотім відмовляється запускати без аргументів. Зауважте, що це помилка /usr/bin/timeне помилки від bash.

Причиною того, що функція зворотного галочки працює в тому, що зворотна галочка перестає timeінтерпретуватися як спеціальний елемент у трубопроводі.

тобто із зворотним галочкою:

`time`;date

вона розбита як два трубопроводи:

1. `time`
2. date

Пам'ятайте, що трубопровід, в нашому випадку, це:

[time] command

і проблема спочатку полягала в тому, що у нас не timeбуло команди, яка заборонена. Але тепер ми просто маємо команду:

`time`

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

Тож bash виконує вбудований timeбез аргументів, що прийнято. Він не дає результатів, і ми не бачимо помилок.

Зауважте, що:

`time`

фактично запускає результат з timeвбудованою, тобто він працює незалежно від timeвбудованого виробляє на стандартний висновок. Але оскільки timeсамостійно нічого не пише в stdout, схоже, це працює.

Нарешті, було помічено, що це працює:

time ; ; date

чого я не можу пояснити, на жаль :)


Я думаю, що ваше пояснення краще, але воно все ще виглядає дивно. ;dateдає bash: syntax error near unexpected token ;, але time ;dateдає bash: syntax error near unexpected token date, тому, схоже, bash не трактує команду після вбудованого часу як "; date". Цікаво, що time ; ; dateпрацює.
влаштовуйте

так, дякую @arrange, це дуже дивно. Відповідь я трохи оновлю.
cdmackay

добре, @ домовитись, переписали. Досі не можу пояснити ваш останній хоч ... зітхання.
cdmackay

@cdmackay Ви змішуєте основи та цитати. При цитуванні 'time' вона втрачає своє значення як зарезервоване слово. Зворотний відтиск змушує його виконувати в підзаголовку, вихід якого з'єднується з командою. Це не має нічого спільного з дискусією. Власне, ваш приклад `time\';dateдоводить протилежне ваше твердження: це повинно дати помилку вашим міркуванням, оскільки /usr/bin/timeвимагає аргументу. Причина цього не полягає в тому, що в нижній частині, в якій він виконується, timeзнову зарезервоване слово .
zwets

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