Как grep для нескольких шаблонов?

Я хочу найти все строки в нескольких файлах, которые соответствуют одному из двух шаблонов. Я попытался найти шаблоны, которые я ищу, набрав

grep (foo|bar) *.txt 

но оболочка интерпретирует | как труба и жалуется, когда bar не является исполняемым.

Как я могу использовать grep для нескольких шаблонов в одном и том же наборе файлов?

9 Solutions collect form web for “Как grep для нескольких шаблонов?”

Во-первых, вам нужно защитить шаблон от расширения оболочкой. Самый простой способ сделать это – установить одинарные кавычки вокруг него. Одиночные кавычки предотвращают расширение чего-либо между ними (включая обратную косую черту); единственное, что вы не можете сделать, это одинарные кавычки в шаблоне.

 grep 'foo*' *.txt 

Если вам нужна одна цитата, вы можете записать ее как '\'' (конец строки, литерал, литерал открытой строки).

 grep 'foo*'\''bar' *.txt 

Во-вторых, grep поддерживает два синтаксиса для шаблонов. Старый синтаксис по умолчанию ( основные регулярные выражения ) не поддерживает оператор чередования ( | ), хотя некоторые версии имеют его как расширение, но написаны с обратной косой чертой.

 grep 'foo\|bar' *.txt 

Портативный способ – использовать более новый синтаксис, расширенные регулярные выражения . Вам нужно передать параметр -E в grep чтобы выбрать его. В Linux вы также можете ввести egrep вместо grep -E (в других организациях вы можете сделать это псевдоним).

 grep -E 'foo|bar' *.txt 

Другая возможность, когда вы просто ищете какой-либо из нескольких шаблонов (в отличие от создания сложного шаблона с использованием дизъюнкции), – это передать несколько шаблонов grep . Вы можете сделать это, пропустив каждый шаблон с помощью опции -e .

 grep -e foo -e bar *.txt 
 egrep "foo|bar" *.txt 

или

 grep "foo\|bar" *.txt grep -E "foo|bar" *.txt 

выборочно ссылаясь на man-страницу gnu-grep:

  -E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below). (-E is specified by POSIX.) Matching Control -e PATTERN, --regexp=PATTERN Use PATTERN as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-). (-e is specified by POSIX.) 

(…)

  grep understands two different versions of regular expression syntax: “basic” and “extended.” In GNU grep, there is no difference in available functionality using either syntax. In other implementations, basic regular expressions are less powerful. The following description applies to extended regular expressions; differences for basic regular expressions are summarized afterwards. 

Вначале я не читал дальше, поэтому я не узнал тонких различий:

 Basic vs Extended Regular Expressions In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \). 

Я всегда использовал egrep и бесполезно parens, потому что я учился на примерах. Теперь я узнал что-то новое. 🙂

Как сказал TC1, -F кажется, можно использовать:

 $> cat text some text foo another text bar end of file $> patterns="foo bar" $> grep -F "${patterns}" text foo bar 

Во-первых, вам нужно использовать кавычки для специальных символов. Во-вторых, даже так, что grep не будет понимать чередование напрямую; вам нужно будет использовать egrep или (только с GNU grep ) grep -E .

 egrep 'foo|bar' *.txt 

(Скобки не нужны, если чередование не является частью большого регулярного выражения.)

Если вам не нужны регулярные выражения, гораздо быстрее использовать fgrep или grep -F с несколькими параметрами -e, например:

 fgrep -efoo -ebar *.txt 

fgrep (альтернативно grep -F ) намного быстрее обычного grep, потому что он ищет фиксированные строки вместо регулярных выражений.

У меня были журналы доступа, где даты, где глупо отформатированы: [30 / июн / 2013: 08: 00: 45 +0200]

но мне нужно было отобразить его как: 30 / июня / 2013 08:00:45

Проблема в том, что, используя «OR» в моей команде grep, я получал 2 выражения соответствия на 2 выделенных строках.

Вот решение:

 grep -in myURL_of_interest *access.log | \ grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)' \ | paste - - -d" " > MyAccess.log 

Я надеюсь, что это помогает 🙂

Вы можете попробовать следующую команду, чтобы получить результат:

 egrep 'rose.*lotus|lotus.*rose' some_file 

Дешевый и веселый способ grep для нескольких шаблонов:

 $ echo "foo" > ewq ; echo "bar" >> ewq ; grep -H -f ewq *.txt ; rm ewq 

Это работает для меня

 root@gateway:/home/sshuser# aws ec2 describe-instances --instance-ids i-2db0459d |grep 'STATE\|TAG' **STATE** 80 stopped **STATE**REASON Client.UserInitiatedShutdown Client.UserInitiatedShutdown: User initiated shutdown **TAGS** Name Magento-Testing root@gateway:/home/sshuser# 
  • сравнить 2 столбца из 2 разных CSV-файлов
  • Обработка путей в файле m3u
  • Отображает и их относительное положение в сценарии оболочки
  • Развернуть переменную среды из PIPE (SHELL)
  • как grep для c: \
  • Только цифры sh и grep
  • xargs не запрашивает после каждой строки
  • Как получить только имена подпапок, состоящие только из верхних букв?
  • Установить уровень сжатия LZMA через tar
  • Скрипт должен читать эхо-строку
  • Сравните размер файла нескольких файлов в массиве
  • Linux и Unix - лучшая ОС в мире.