Как я могу grep для того или иного (2 вещи) в файле?


38

У меня есть файл с "тогда" и "там".

Я могу

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

и я могу

$ grep "there " x.x
If there is no blob none some will be created

Как я могу найти оба в одной операции? Я пытался

$ grep (then|there) x.x

-bash: синтаксическая ошибка рядом с неожиданным токеном `('

а также

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

Ответы:


54

Вы должны поставить выражение в кавычки. Ошибка, которую вы получаете, является результатом интерпретации bash (как специального символа.

Также вам нужно указать grep использовать расширенные регулярные выражения.

$ grep -E '(then|there)' x.x

Без расширенных регулярных выражений, придется бежать |, (и ). Обратите внимание, что здесь мы используем одинарные кавычки. Bash специально обрабатывает обратную косую черту в двойных кавычках.

$ grep '\(then\|there\)' x.x

Группировка не нужна в этом случае.

$ grep 'then\|there' x.x

Это было бы необходимо для чего-то вроде этого:

$ grep 'the\(n\|re\)' x.x

3
Смотрите также grep $'then\nthere'и grep -e then -e there. Обратите внимание, что \|это не является стандартным в BRE. Остальное есть. Bash обрабатывает обратные косые специально в двойных кавычках только до ", $, \ , `и символ новой строки.
Стефан Шазелас

1
Какова цель x.x?
Алекс

7

Просто быстрое дополнение, большинство разновидностей имеют команду egrep, которая просто grep с -E. Мне лично нравится гораздо лучше печатать

egrep "i(Pod|Pad|Phone)" access.log

Чем использовать grep -E


2

Материал, задокументированный в разделе РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ на (или, по крайней мере, моей) справочной странице, на самом деле предназначен для расширенных регулярных выражений;

grep понимает три разные версии синтаксиса регулярных выражений: «базовый», «расширенный» и «perl». В GNU grep нет различий в доступной функциональности между базовым и расширенным синтаксисами. В других реализациях базовые регулярные выражения менее мощны. Следующее описание относится к расширенным регулярным выражениям; различия для основных регулярных выражений суммируются впоследствии.

Но grep не использует их по умолчанию - вам нужен -Eпереключатель:

grep "(then|there)" x.x

Потому что (снова из справочной страницы):

Основные против расширенных регулярных выражений

В основных регулярных выражениях метасимволы?, +, {, |, (И) теряют свое особое значение; вместо этого используйте версии с обратной косой чертой \ ?, +, {, \ |, (и).

Так что вы также можете использовать:

grep "then\|there" x.x

Так как скобки в данном случае излишни.


0

Элегантная простота 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:

эхо "(тогда | там)" хх
(тогда | там) хх

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.