Как найти шаблоны через несколько строк с помощью grep?

Я хочу найти файлы, которые имеют "abc" И "efg" в том порядке, и те две строки находятся на различных строках в том файле. Например: файл с содержанием:

blah blah..
blah blah..
blah abc blah
blah blah..
blah blah..
blah blah..
blah efg blah blah
blah blah..
blah blah..

Должен быть подобран.

190
задан codeforester 3 September 2018 в 09:43
поделиться

6 ответов

Grep недостаточно для этой операции.

pcregrep , который встречается в большинстве современных систем Linux, может использоваться как

pcregrep -M  'abc.*(\n|.)*efg' test.txt

, где -M, --multiline позволяют шаблонам соответствовать более чем одной строке

Существует более новый pcre2grep также. Оба предоставлены проектом PCRE .

pcre2grep доступен для Mac OS X через Порты Mac как часть порта pcre2 :

% sudo port install pcre2 

и через Homebrew как:

% brew install pcre

или для pcre2

% brew install pcre2
203
ответ дан 23 November 2019 в 05:35
поделиться

Это можно сделать очень легко, если вы умеете использовать Perl.

perl -ne 'if (/abc/) { $abc = 1; next }; print "Found in $ARGV\n" if ($abc && /efg/); }' yourfilename.txt

Вы также можете сделать это с помощью одного регулярного выражения, но для этого нужно объединить все содержимое файла в одну строку, что может привести к тому, что большие файлы займут слишком много памяти. Для полноты, вот этот метод:

perl -e '@lines = <>; $content = join("", @lines); print "Found in $ARGV\n" if ($content =~ /abc.*efg/s);' yourfilename.txt
6
ответ дан 23 November 2019 в 05:35
поделиться

Я не уверен, возможно ли это с grep, но sed упрощает его:

sed -e '/abc/,/efg/!d' [file-with-content]
110
ответ дан 23 November 2019 в 05:35
поделиться

Я не знаю, как бы я сделал это с помощью grep, но я бы сделал что-то вроде этого с awk:

awk '/abc/{ln1=NR} /efg/{ln2=NR} END{if(ln1 && ln2 && ln1 < ln2){print "found"}else{print "not found"}}' foo

Однако вы должны быть осторожны, как вы это делаете. Вы хотите, чтобы регулярное выражение соответствовало подстроке или всему слову? при необходимости добавьте теги \ w. Кроме того, хотя это строго соответствует тому, как вы указали пример, это не совсем работает, когда abc появляется второй раз после efg. Если вы хотите справиться с этим, добавьте, если необходимо, в / abc / case и т. Д.

5
ответ дан 23 November 2019 в 05:35
поделиться
#!/bin/bash
shopt -s nullglob
for file in *
do
 r=$(awk '/abc/{f=1}/efg/{g=1;exit}END{print g&&f ?1:0}' file)
 if [ "$r" -eq 1 ];then
   echo "Found pattern in $file"
 else
   echo "not found"
 fi
done
1
ответ дан 23 November 2019 в 05:35
поделиться

К сожалению, вы не можете. Из документации grep :

grep ищет именованные входные ФАЙЛЫ (или стандартный ввод, если файлы не имеют имен или если в качестве имени файла указан один дефис-минус (-)) для строки , содержащие совпадение с заданным ШАБЛОНОМ.

3
ответ дан 23 November 2019 в 05:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: