Сопоставьте две строки в одной строке с grep - PullRequest
191 голосов
/ 20 декабря 2010

Я пытаюсь использовать grep для сопоставления строк, которые содержат две разные строки. Я пробовал следующее, но это соответствует строки, которые содержат string1 или string2 , что не то, что я хочу.

grep 'string1\|string2' filename

Так как же сопоставить с grep только строки, содержащие обе строки ?

Ответы [ 20 ]

193 голосов
/ 20 ноября 2012

Я думаю, это то, что вы искали:

grep -E "string1|string2" filename

Я думаю, что ответы так:

grep 'string1.*string2\|string2.*string1' filename

соответствуют только случаю, когда оба присутствуют, а не один илидругой или оба.

164 голосов
/ 20 декабря 2010

Вы можете использовать grep 'string1' filename | grep 'string2'

Или grep 'string1.*string2\|string2.*string1' filename

26 голосов
/ 26 декабря 2013

Для поиска файлов, содержащих все слова в любом порядке в любом месте:

grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'

Первый grep запускает рекурсивный поиск (r), игнорируя регистр (i) и перечисляя (распечатывая) имена файлов, которые соответствуют (l) для одного термина ('action') с одинарными кавычками) в любом месте файла.

Последующий greps ищет другие термины, сохраняя нечувствительность к регистру и перечисляя соответствующие файлы.

Окончательный список файлов, которые вы получите, будет содержать эти термины в любом порядке в любом месте файла.

14 голосов
/ 20 декабря 2010

Если у вас есть grep с опцией -P для ограниченного регулярного выражения perl, вы можете использовать

grep -P '(?=.*string1)(?=.*string2)'

, что дает преимущество работы с перекрывающимися строками.Несколько проще использовать perl как grep, потому что вы можете указать логику и непосредственно:

perl -ne 'print if /string1/ && /string2/'
12 голосов
/ 09 апреля 2014

Ваш метод был почти хорош, пропустил только -w

grep -w 'string1\|string2' filename
7 голосов
/ 20 декабря 2010

Вы можете попробовать что-то вроде этого:

(pattern1.*pattern2|pattern2.*pattern1)
5 голосов
/ 20 декабря 2010

Оператор | в регулярном выражении означает или. То есть будут совпадать либо string1, либо string2. Вы могли бы сделать:

grep 'string1' filename | grep 'string2'

, который передаст результаты первой команды во второй grep. Это должно дать вам только те строки, которые соответствуют обоим.

3 голосов
/ 17 ноября 2017

А поскольку люди предлагали Perl и Python, а также замысловатые сценарии оболочки, здесь простой awk подход:

awk '/string1/ && /string2/' filename

Посмотрев на комментарии к принятому ответу: нет, этоне делает многострочным;но это также не то, о чем просил автор вопроса.

2 голосов
/ 27 апреля 2017

Найдены строки, которые начинаются только с 6 пробелов и заканчиваются:

 cat my_file.txt | grep
 -e '^      .*(\.c$|\.cpp$|\.h$|\.log$|\.out$)' # .c or .cpp or .h or .log or .out
 -e '^      .*[0-9]\{5,9\}$' # numers between 5 and 9 digist
 > nolog.txt
2 голосов
/ 05 октября 2017

Допустим, нам нужно найти количество слов в тестовом файле. Есть два способа сделать это

1) Использовать команду grep с шаблоном сопоставления регулярных выражений

grep -c '\<\(DOG\|CAT\)\>' testfile

2) Используйте команду egrep

egrep -c 'DOG|CAT' testfile 

С egrep вам не нужно беспокоиться о выражении, а просто разделяйте слова с помощью разделителя канала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...