Как найти шаблоны по нескольким строкам, используя grep? - PullRequest
184 голосов
/ 21 апреля 2010

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

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

Должно совпадать.

Ответы [ 23 ]

3 голосов
/ 22 апреля 2010

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

grep ищет именованные входные ФАЙЛЫ (или стандартный ввод, если не названы файлы, или если в качестве имени файла указан один дефис-минус (-))1005 * строк , содержащих совпадение с заданным шаблоном.

2 голосов
/ 27 октября 2011

Хотя опция sed самая простая и легкая, однострочная LJ, к сожалению, не самая портативная. Тем, кто застрял с версией C Shell, нужно избежать ударов:

sed -e '/abc/,/efg/\!d' [file]

Это, к сожалению, не работает в Bash и др.

2 голосов
/ 05 сентября 2015

Если вам нужно, чтобы оба слова были близко друг к другу, например, не более 3 строк, вы можете сделать это:

find . -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"

Тот же пример, но фильтрация только * .txt файлов:

find . -name *.txt -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"

А также вы можете заменить команду grep на команду egrep, если вы также хотите найти с регулярными выражениями.

2 голосов
/ 10 марта 2014

Если вы хотите использовать контексты, этого можно достичь, набрав

grep -A 500 abc test.txt | grep -B 500 efg

Это покажет все между"abc" и "efg", если они находятся в пределах 500 строк друг от друга.

1 голос
/ 28 марта 2019

Я использовал это, чтобы извлечь последовательность фаста из мультифаст-файла, используя опцию -P для grep:

grep -Pzo ">tig00000034[^>]+" file.fasta > desired_sequence.fasta

-P для поисков на основе Perl -z для окончания строки в 0 байтов вместо символа новой строки -o просто захватить то, что совпало, так как grep возвращает всю строку (что в данном случае, так как вы сделали -z это весь файл) Ядром регулярного выражения является [^>], что означает «не больше, чем символ»

1 голос
/ 22 апреля 2010
#!/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 голос
/ 14 января 2015

С серебряным искателем :

ag 'abc.*(\n|.)*efg'

аналогично ответу на предъявителя кольца, но вместо этого используется ag. Скоростные преимущества серебряного искателя могли бы здесь проявиться.

1 голос
/ 24 февраля 2012

вы можете использовать grep, если вы не заинтересованы в последовательности паттерна.

grep -l "pattern1" filepattern*.* | xargs grep "pattern2"

пример

grep -l "vector" *.cpp | xargs grep "map"

grep -l найдет все файлы, которые соответствуют первому шаблону, а xargs найдет второй шаблон. Надеюсь, это поможет.

0 голосов
/ 14 мая 2019

Если у вас есть некоторая оценка расстояния между двумя строками 'abc' и 'efg', которые вы ищете, вы можете использовать:

grep -r.-e 'abc' -A num1 -B num2 |grep 'efg'

Таким образом, первый grep будет возвращать строку со строками 'abc' плюс # num1 после него и # num2 после него, а второй grepпросеять через все это, чтобы получить «EFG».Тогда вы узнаете, в каких файлах они появляются вместе.

0 голосов
/ 15 апреля 2018

filepattern *.sh важен для предотвращения проверки каталогов. Конечно, некоторые тесты могут это предотвратить.

for f in *.sh
do
  a=$( grep -n -m1 abc $f )
  test -n "${a}" && z=$( grep -n efg $f | tail -n 1) || continue 
  (( ((${z/:*/}-${a/:*/})) > 0 )) && echo $f
done

The

grep -n -m1 abc $f 

ищет не более 1 соответствия и возвращает (-n) номер белья. Если совпадение найдено (test -n ...), найдите последнее совпадение с efg (найдите все и возьмите последнее с tail -n 1).

z=$( grep -n efg $f | tail -n 1)

еще продолжить.

Поскольку в результате получается что-то вроде 18:foofile.sh String alf="abc";, нам нужно сократить значение от ":" до конца строки.

((${z/:*/}-${a/:*/}))

Должен возвращать положительный результат, если последнее совпадение 2-го выражения прошло после первого совпадения первого.

Затем мы сообщаем имя файла echo $f.

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