Я хочу найти все строки в нескольких файлах, которые соответствуют одному из двух шаблонов. Я попытался найти шаблоны, которые я ищу, набрав
grep (foo|bar) *.txt
но оболочка интерпретирует это |
как канал и жалуется, когда bar
не является исполняемым файлом.
Как я могу grep для нескольких шаблонов в одном наборе файлов?
Ответы:
Во-первых, вам нужно защитить шаблон от расширения оболочкой. Самый простой способ сделать это - заключить в него одинарные кавычки. Одинарные кавычки предотвращают расширение чего-либо между ними (включая обратную косую черту); единственное, что вы не можете сделать, - это использовать одинарные кавычки в шаблоне.
Если вам нужна одиночная кавычка, вы можете написать ее как
'\''
(конец строкового литерала, буквальная кавычка, открытая строковый литерал).Во-вторых, grep поддерживает два синтаксиса для шаблонов. Старый синтаксис по умолчанию ( базовые регулярные выражения ) не поддерживает
|
оператор alternation ( ), хотя некоторые версии имеют его как расширение, но пишутся с обратной косой чертой.Переносимым способом является использование более нового синтаксиса, расширенных регулярных выражений . Вам нужно передать
-E
опцию,grep
чтобы выбрать его. В Linux вы также можете печататьegrep
вместоgrep -E
(в других единицах вы можете сделать это псевдонимом).Другой возможностью, когда вы просто ищете какой-либо из нескольких шаблонов (в отличие от построения сложного шаблона с использованием дизъюнкции), является передача нескольких шаблонов
grep
. Вы можете сделать это, предшествуя каждому шаблону с-e
опцией.источник
fgrep
илиgrep -F
, для небольших моделей разница будет незначительной, но по мере того, как они станут длиннее, преимущества начнут проявляться ...grep -F
имеет ли реальный выигрыш в производительности, зависит от реализации grep: некоторые из них в любом случае применяют один и тот же алгоритм, так что-F
это влияет только на время, затрачиваемое на анализ шаблона, а не на время поиска.-F
Например, GNU grep работает не быстрее (в нем также есть ошибка, которая делаетgrep -F
медленнее в многобайтовых локалях - тот же шаблон констант наgrep
самом деле значительно быстрее!). С другой стороны, BusyBox grep извлекает большую выгоду из-F
больших файлов.egrep
предшествуетgrep -E
. Это не специфично для GNU (это, безусловно, не имеет ничего общего с Linux). На самом деле, вы все равно найдете системы, такие как Solaris, где по умолчаниюgrep
все еще не поддерживается-E
.или же
выборочно цитируя справочную страницу gnu-grep:
(...)
В начале я не читал дальше, поэтому я не узнал тонких различий:
Я всегда использовал egrep и ненужные парены, потому что я учился на примерах. Теперь я узнал что-то новое. :)
источник
Как сказал ТС1,
-F
похоже, пригодный вариант:источник
Во-первых, вам нужно использовать кавычки для специальных символов. Во-вторых, даже в этом случае,
grep
вы не поймете чередования напрямую; Вы должны будете использоватьegrep
, или (grep
только с GNU )grep -E
.(Скобки не нужны, если чередование не является частью большего регулярного выражения.)
источник
grep -E
стандартнее, чемegrep
.Если вам не нужны регулярные выражения, это гораздо быстрее использовать
fgrep
илиgrep -F
с несколькими параметрами -e, например так:fgrep
(альтернативноgrep -F
) намного быстрее, чем обычный grep, потому что он ищет фиксированные строки вместо регулярных выражений.источник
fgrep
это устарело.Вы можете попробовать приведенную ниже команду, чтобы получить результат:
источник
Дешевый и веселый способ поиска нескольких шаблонов:
источник
-f
опция grep принимает файл с несколькими шаблонами. Вместо создания временного файла (который вы можете потом забыть удалить), просто используйте подстановку процесса оболочки:grep -f <(echo foo; echo bar) *.txt
Pipe (
|
) - это специальный символ оболочки, поэтому его необходимо либо экранировать (\|
), либо заключить в кавычки в соответствии с инструкциями manual (man bash
):Смотрите: Каких персонажей нужно экранировать в Bash?
Вот несколько примеров (с использованием еще не упомянутых инструментов):
Использование
ripgrep
:rg "foo|bar" *.txt
rg -e foo -e bar *.txt
Использование
git grep
:git grep --no-index -e foo --or -e bar
Примечание. Он также поддерживает логические выражения, такие как
--and
,--or
и--not
.Для операции AND на строку смотрите: Как запустить grep с несколькими шаблонами AND?
Для операции AND для файла см .: Как проверить, существует ли в файле несколько строк или регулярных выражений?
источник
У меня были журналы доступа, где даты были тупо отформатированы: [30 / Jun / 2013: 08: 00: 45 +0200]
Но мне нужно было отобразить это как: 30 июня 2013 года 08:00:45
Проблема в том, что, используя «OR» в моем выражении grep, я получал два выражения соответствия в двух отдельных строках.
Вот решение:
источник
TL; DR: если вы хотите сделать больше вещей после сопоставления с одним из множества шаблонов, заключите их, как в
\(pattern1\|pattern2\)
пример: я хочу найти все места, где переменная, которая содержит имя «date», определяется как String или int. (например, "int cronDate =" или "String textFormattedDateStamp ="):
С помощью
grep -E
вам не нужно избегать скобок или трубы, т. Е.grep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='
источник
Это работает для меня
источник
Есть несколько способов сделать это.
grep 'foo\|bar' *.txt
egrep 'foo|bar' *.txt
find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'
3-й и 4-й вариант будут выполнять grep только в файлах и избегать каталогов с
.txt
их именами.Таким образом, в соответствии с вашим вариантом использования, вы можете использовать любой из вариантов, упомянутых выше.
Спасибо!!
источник
чтобы добавить к ответу @ geekosaur , если у вас есть несколько шаблонов, которые также содержат вкладки и пробел, вы используете следующую команду
где
[[:blank:]]
класс символов RE, представляющий пробел или символ табуляцииисточник