Елегантна простота Баша, схоже, загубиться на величезній сторінці чоловіка.
На додаток до відмінних рішень вище, я думав, що спробую дати вам шпаргалку щодо того, як баш розбирає та інтерпретує заяви . Потім, використовуючи цю дорожню карту, я розберу приклади, подані запитуючим, щоб допомогти вам краще зрозуміти, чому вони не працюють за призначенням.
Примітка: рядки сценарію оболонки використовуються безпосередньо. Введені рядки введення спочатку розширюються історією.
Кожна лінія bash спочатку токенізується , або іншими словами подрібнюється до того, що називається лексемами . (Токенізація відбувається перед усіма іншими розширеннями, включаючи дужку, тильду, параметр, команду, арифметику, процес, розбиття слів та розширення імені файлу.)
Тут лексема означає частину вхідного рядка, розділеного (обмеженого) одним із цих спеціальних мета-символів:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash використовує багато інших спеціальних символів, але лише ці 10 видають початкові жетони.
Однак, оскільки ці мета-символи також іноді повинні використовуватися в токені, повинен бути спосіб позбавити їх особливого значення. Це називається втечею. Екранування здійснюється або процитувати рядки з одного або декількох символів (тобто 'xx..'
, "xx.."
), або випереджаючи індивідуальний характер з задніми косими рисами, (тобто \x
). (Це трохи складніше, ніж це, тому що цитати також потрібно цитувати, і тому, що подвійні цитати не цитують все, але це спрощення зробить поки що.)
Не плутайте баш-цитування з ідеєю цитування рядка тексту, як на інших мовах. Між цитатами в bash - це не рядки, а розділи рядка введення, у якому вийшли метасимволи, щоб вони не розмежовували лексеми.
Зауважте, важлива різниця між '
, і "
, але це вже на інший день.
Решта мета-символів, які не були розроблені, потім стають розділювачами лексем.
Наприклад,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
У першому прикладі є два жетони, отримані роздільником пробілу: echo
і xyz
.
Аналогічно у 2-му прикладі.
У третьому прикладі крапка з комою уникли, таким чином , є 4 жетони , отримані космічним роздільником, echo
, x;
, echo
, і y
. Перший жетон запускається як команда і бере наступні три лексеми як вхідні дані. Зауважте, 2-й echo
не виконується.
Важливо пам’ятати, що спочатку bash шукає втеча символів ( '
, "
і, \
), а потім шукає нерозміщені роздільники мета-символів у такому порядку.
Якщо не уникнути, то ці 10 спеціальних символів служать token
розмежувачами. Деякі з них також мають додаткове значення, але в першу чергу вони є розмежувачами лексем.
Який греп очікує
У наведеному вище прикладі Grep потрібні ці маркери, grep
, string
, filename
.
Першою спробою питання було:
$ grep (тоді | там) xx
В цьому випадку (
, )
і |
є неекрановані символи мета і тому служать для поділу входу в ці маркери: grep
, (
, then
, |
, there
, )
, і x.x
. Grep хоче бачити grep
, then|there
і x.x
.
Друга спроба питання:
grep "(тоді | там)" xx
Це розмічає в grep
, (then|there)
, x.x
. Це можна побачити, якщо ви поміняєте grep на ехо:
відлуння "(тоді | там)" xx
(тоді | там) xx