Como posso procurar um padrão de múltiplas linhas em um arquivo?

Eu precisava encontrar todos os arquivos que continham um padrão de string específico. A primeira solução que vem à mente é usando o find piped com xargs grep :

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN' 

Mas se eu precisar encontrar padrões que se estendam em mais de uma linha, estou preso porque o vanilla grep não consegue encontrar padrões de múltiplas linhas.

Então, descobri o pcregrep que significa GREP Compatible Compatible Regular Expressions .

Por exemplo, você precisa encontrar arquivos em que a variável ‘ _name ‘ seja imediatamente seguida pela variável ‘ _description ‘:

 find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description' 

Dica: você precisa include o caractere de quebra de linha no seu padrão. Dependendo da sua plataforma, pode ser ‘\ n’, \ r ‘,’ \ r \ n ‘, …

Por que você não vai por awk :

 awk '/Start pattern/,/End pattern/' filename 

Aqui está o exemplo usando o GNU grep :

 grep -Pzo '_name.*\n.*_description' 

-z / --null-data Trate --null-data input e saída como sequências de linhas.

grep -P também usa a libpcre, mas é muito mais amplamente instalado. Para encontrar uma seção de title completa de um documento html, mesmo que ele ocupe várias linhas, você pode usar isto:

 grep -P '(?s).*' example.html 

Como o projeto PCRE implementa o padrão perl, use a documentação do perl para referência:

Aqui está um exemplo mais útil:

 pcregrep -Mi "(.*\n){0,5}" afile.html 

Ele pesquisa a tag de título em um arquivo html, mesmo que se estenda por várias linhas.

Com o pesquisador de prata :

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

Otimizações de velocidade do pesquisador de prata poderiam brilhar aqui.

Você pode usar a alternativa grep peneirar aqui (disclaimer: Eu sou o autor).

Suporta a correspondência multilinha e limita a pesquisa a tipos de arquivos específicos prontos para uso:

  sift -m --files '* .py' 'YOUR_PATTERN' 

(pesquisa todos os arquivos * .py para o padrão de regex multilinha especificado)

Está disponível para todos os principais sistemas operacionais. Dê uma olhada na página de amostras para ver como ela pode ser usada para extrair valores de múltiplas linhas de um arquivo XML.

Essa resposta pode ser útil:

Regex (grep) para pesquisa em várias linhas

Para encontrar recursivamente, você pode usar os sinalizadores -R (recursivo) e –include (padrão GLOB). Vejo:

Use grep –exclude / – inclua a syntax para não usar determinados arquivos

 perl -ne 'print if (/begin pattern/../end pattern/)' filename 

Usando o editor ex / vi e a opção globstar (syntax semelhante a awk e sed ):

 ex +"/string1/,/string3/p" -R -scq! file.txt 

onde aaa é o seu ponto de partida e bbb é o seu texto final.

Para pesquisar recursivamente, tente:

 ex +"/aaa/,/bbb/p" -scq! **/*.py 

Nota: Para ativar a syntax ** , execute shopt -s globstar (Bash 4 ou zsh).

@Marcin: awk example não-ganancioso:

 awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename