Элегантная простота Bash, похоже, теряется в его огромной справочной странице.
В дополнение к превосходным решениям, описанным выше, я подумал, что постараюсь дать вам шпаргалку о том, как bash анализирует и интерпретирует утверждения . Затем, используя эту дорожную карту, я проанализирую примеры, представленные спрашивающим, чтобы помочь вам лучше понять, почему они не работают должным образом.
Примечание: строки сценария оболочки используются напрямую. Типизированные строки ввода сначала раскрываются в истории.
Каждая строка bash сначала маркируется токенами , или другими словами, врезается в так называемые токены . (Токенизация происходит перед всеми другими расширениями, включая фигурные скобки, тильду, параметр, команду, арифметику, процесс, разбиение слов и расширение имени файла.)
Токен здесь означает часть строки ввода, разделенную (разделенную) одним из следующих специальных метасимволов:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash использует много других специальных символов, но только эти 10 производят начальные токены.
Однако, поскольку эти метасимволы также иногда должны использоваться в токене, должен быть способ убрать их особое значение. Это называется побег. Экранирование осуществляется либо процитировать строки из одного или нескольких символов (то есть 'xx..'
, "xx.."
), или предваряя индивидуальный характер с задними косыми чертами, (т.е. \x
). (Это немного сложнее, чем это, потому что кавычки также должны быть заключены в кавычки, и потому что двойные кавычки не заключают в кавычки все, но это упрощение пока подойдет.)
Не путайте цитирование bash с идеей цитирования строки текста, как в других языках. То, что находится между кавычками в bash, это не строки, а разделы входной строки, у которых экранированы метасимволы, чтобы они не разделяли токены.
Обратите внимание, между ними есть важное различие '
, "
но это касается другого дня.
Оставшиеся неэкранированные метасимволы становятся разделителями токенов.
Например,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
В первом примере есть два токена, создаваемых разделителем пробелов: echo
и xyz
.
Аналогично во 2-м примере.
В третьем примере точка с запятой избежали, таким образом , есть 4 жетоны , полученные космическим разделителем, echo
, x;
, echo
, и y
. Первый токен затем запускается как команда и принимает следующие три токена в качестве входных данных. Обратите внимание, 2-й echo
не выполняется.
Важно помнить о том , что Баш сначала ищет вылетающие символы ( '
, "
и \
), а затем ищет неэкранированные разделители меты-символы, в этом порядке.
Если не удалось избежать, то эти 10 специальных символов служат token
разделителями. Некоторые из них также имеют дополнительное значение, но, в первую очередь, они являются разделителями токенов.
Что ожидает grep
В приведенном выше примере 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 на echo:
эхо "(тогда | там)" хх
(тогда | там) хх