Наприклад, наступна команда не працює:
if [[-e xyz]]; then echo File exists;fi
ksh видає таку помилку
[[-e: command not found
Це тому, що "[[-" є неоднозначним?
Наприклад, наступна команда не працює:
if [[-e xyz]]; then echo File exists;fi
ksh видає таку помилку
[[-e: command not found
Це тому, що "[[-" є неоднозначним?
Відповіді:
Найпростіше пояснення буде, тому що в керівництві він виглядає [[ expression ]]так , там має бути простір між [[та expressionі закривання ]]. Але, звичайно, ми можемо спробувати поглянути на це більш глибоко. Оболонки мають дещо складну граматику і значною мірою покладаються на поняття "розщеплення слів". Зокрема, в посібнику ksh (1) зазначено:
Оболонка починає розбирати свої дані, розбиваючи її на слова. Слова, що є послідовностями символів, розмежовуються символами пробілу без процитів (пробіл, вкладка та новий рядок) або мета-символами (<,>, |,;,, і, (і)). Крім розмежування слів, пробіли та вкладки ігноруються, а нові рядки зазвичай розмежовують команди.
Отже, як зазначено в посібнику, послідовність символів [[-eвважається оболонковим словом. kshшукає таку команду у списку вбудованих та спеціальних операторів (як-от forабо while), потім шукає зовнішню команду - і voilà - жодної не знайдено, отже, повідомлення про помилку про команду не знайдено.
У цьому випадку [[також не є спеціальними мета-символами. Якби вони були, -eчастина в [[-eних вважалася б оболонковим словом, а не аргументом для [[себе. Однак [[описується як складна команда, а в посібнику сказано наступне:
Складені команди створюються за допомогою наступних зарезервованих слів - ці слова розпізнаються лише в тому випадку, якщо вони не цитуються і якщо вони використовуються як перше слово команди (тобто, їм не може передувати призначення параметрів або перенаправлення):
Отже, [[щоб бути визнаним складною командою, воно повинно бути першим словом команди чи списку команд, яке, згідно з попереднім визначенням слова, означає, що воно повинно бути відокремлене пробілами, вкладками чи новими рядками від інших слова / аргументи.
Ви запитали в коментарях : "Чому парсер не може зупинитися, як тільки він знайде" [["шаблон, і розглядає це як початок умовної команди?" Коротка відповідь, ймовірно, тому, що 1) вплив [синтаксису, оскільки він був спочатку зовнішньою командою, а для відповідності POSIX стандарт існує як зовнішня команда навіть сьогодні, і 2) тому, що аналізатор оболонки побудований так. Шілл-аналізатор може розпізнати інші спеціальні символи, відмінні від простору: echo $((2+2))і (echo foobar)працювати чудово. Можливо, у майбутньому, коли kshрозвиток почне відновитись або з'явиться форк або клон (як-от mkshабо pdksh), хтось реалізує синтаксис, що не має місця [[-e.
[[її називають "зарезервованим словом" (див. Розділ 2.9 мови командної оболонки ). За визначенням POSIX, зарезервоване слово має бути розділене пробілами. На противагу цьому (- оператор, а стандартні стани в розділі 2.9 "представлення включають проміжки між лексемами в тих місцях, де <blank>s не буде необхідним (коли один з жетонів є оператором)". Дивіться пов’язану дискусію: Граматика оболонки POSIX: Чому груповій групі потрібне перше місце, але її немає?char- це ключове слово, але ви все ще не можете писати charsomeletter = 'A';і очікуєте, що аналізатор зупиниться після перегляду char.
i--<=++j, і у компілятора немає проблем з тим, що розбирати як i -- <= ++ j.
_). Ksh має (як оператора , а (echo hello)розбирає як ( echo hello ). Це if, {, [[та інші ключові слова , і ifx, {xі [[xкожен один маркер - наприклад , як charsomeletterце один C маркер. Навпаки, без котирування (xв ksh є два лексеми - як, як i--це два лексеми в C. Те, що це концептуально навіть означає бути оператором, відрізняється між оболонками в стилі Борна (як ksh) і C. Але Пітер А. Шнайдер зазначив: реальна лексична схожість.
Важливо зазначити, що [це команда, а ключове слово оболонки [[в bash та ksh засноване на [.
[[використовується аналогічно до [. Іноді ви можете навіть замінити [ ]з [[ ]]без будь - яких змін в поведінці. Як [, як і будь-яка команда, пробіл є обов'язковим між командою та її аргументами. Те саме стосується і [[.
У нас раніше було тільки /usr/bin/[. Зараз більшість оболонок [вбудовані для ефективності, але синтаксис той самий. У снарядах, які надають [[, він функціонує як більш універсальна альтернатива [.
Ось опис для [bash:
$ help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
Так що [еквівалентно test(окрім очікування ]аргументу в самому кінці). help testдасть ще детальніше про це. Ви можете порівняти це help [[.
Існує також довідкова сторінка для зовнішньої команди [( man \[).
У випадку
if [[-e
[ні [[команди немає. Повне слово [[-eє.if [[-eробить його тестом на справжнє / хибне. Так чи існує команда [[-e? Це тому, що "[[-" є неоднозначним?
Так. Або ні. [[-eце те, що це таке: нічого, що оболонка розуміє, тому передбачає, що це її власна команда. ;-)
[[-e- це потенційно правильне (якщо дивно виглядає) ім'я команди.
Простір є роздільником та обов'язковий. Як видно з shellcheck:
$ shellcheck gmail-browse-msgs-algorithm.sh
In gmail-browse-msgs-algorithm.sh line 847:
[[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
^-- SC1035: You need a space after the [[ and before the ]].
(І ksh, і bash підтримують [[і не працюють без місця. Shellcheck дає саме такий вихід із аналогічними скриптами ksh та bash, що містять цю помилку.)
Чому потрібні розмежувачі, пов’язані з лексемами та лексиконами .
kshоболонку у питанні. Bash запозичує [[оператору kshі в цьому питанні їх поведінку ідентично, але я був би обережний припущень , оскільки є деякі суттєві відмінності між kshі bashповедінки і внутрішніх органів . Це лише тому, що shellcheck працює на bash script, це може не обов’язково бути відповідним інструментом для ksh-скриптів. Просто щось, про що слід пам’ятати, підходячи до різних снарядів
[[вбудовані правила. Я ні в якому разі не робив висновку, що kshце оболонка, яка shellcheckмогла виявити помилки. Сподіваюся, інші цінують kshі bashє двома різними перекладачами. Дякую, що згадуєте про це. Також варто відзначити [[, що баш вбудований, а [це зовнішня команда.
[це також вбудований в bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Але ви не за горами - [або testпотрібно, щоб бути зовнішньою командою. За часів оригінальної оболонки Борна [насправді була зовнішньою командою, і вона існує дотепер, /usr/bin/[оскільки POSIX вимагає, щоб вона була зовнішньою командою pubs.opengroup.org/onlinepubs/009695399/utilities/test.html В POSIX дуже небагато потрібно бути вбудованим pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Вбудований [для ефективності
ksh; використовувати hashbang або -s ksh. Btw, ksh та bash [["вбудовані", але на відміну від ключового слова , [це вбудована оболонка . (ksh :; whence -v [ [[bash type [ [[:) Вбудовані та зовнішні команди синтаксично однакові. Один із способів [[відрізняється тим [, що [[пригнічує деякі розширення в своїх аргументах, які він не міг би бути вбудованим - настільки ж, як {не міг групувати, якби це був вбудований. Це може бути тому, що {x(або [[x) один маркер відчуває себе дивним. Я думаю, що правильно сказати, що вбудовані та ключові слова лексично, але не синтаксично схожі. @SergiyKolodyazhnyy
[[може бути зовнішньою командою! Тобто це може бути програма, а не якийсь синтаксис, підтримуваний безпосередньо вашою оболонкою. Підтримка синтаксису, що не містить простору, можливо, kshале він не працює в системах із зовнішніми, [[тому з міркувань сумісності краще зберегти необхідний простір.
BusyBox надається [[як зовнішня командаНаприклад, .
Оскільки [[-eможе брати участь у розширенні оболонки (її можна використовувати як
echo [[-e]*
щоб перерахувати всі файли, що починаються з літери між [і eвключно), це було б повним безладом, якби [і ]були спеціальні символи, які не беруть участь у звичайному розщепленні слова, що регулюється пробілом.
[[це ключове слово - імовірно, дерево розбору оболонки вимагає, щоб ключові слова були окреслені пробілом