Padrão de múltiplas linhas Grep


13

Como pesquiso uma frase em várias linhas? Por exemplo, vamos ter a frase "meu chá gelado", que pode ser embrulhada em arquivos de texto:

as js skdfh dfh djh sf my
ice tea.

O grep não será compatível, pois há uma nova linha no meio. Como eu os jogo? Outro padrão multilinha seriapattern1_\n_pattern2

Eu sei que a maneira mais fácil de fazer ATM é apenas grep para uma parte, por exemplo, apenas gelo com a bandeira -A2 -B2 e, em seguida, nessa saída novamente para, por exemplo, chá. Mas isso é muito entediante. Então, eu estou interessado em como você resolveria isso.


1
possível duplicado entre sites: stackoverflow.com/questions/152708/…
Ciro Santilli =

Respostas:


16

Você pode instalar pcregrep(disponível na maioria dos repositórios de distribuição) - o que é grep usando a biblioteca pcre , que faz "Perl Compatible Regular Expressions". Possui uma opção de linha de comando -Mque permite fazer pesquisas em várias linhas - na página do manual :

"A saída para qualquer partida pode consistir em mais de uma linha."

Então você poderia fazer

pcregrep -M 'my\s+ice\s+tea' filename

O \sespaço em branco é, que corresponderá \ne \rno modo multilinha, além dos caracteres de espaço em branco normais. Você também pode combinar o caractere de nova linha diretamente, para que você possa

pcregrep -M 'pattern1_\n_pattern2' filename

+1 legal. nunca ouvi falar, mas tentei e funciona como um encanto!
DaveParillo

Não grep -Efaz padrões PCRE?
Daenyth

3
@Daenyth grep -E na maior parte apenas significa que você pode usar ?, +, {, |, (, e )como o seu significado regex usual sem ter que ter um \ na frente, como você faria se você usar grep padrão. Então grep 'hello\s\+world' fileé equivalente a grep -E 'hello\s+world' file. Não funciona com PCRE. Não é grep -Ppara expressões regulares perl, mas é experimental (de acordo com a página do manual) e eu acho que é um pouco diferente do pcregrep ...
Hamish Downer

1
Sim, eu estava pensando -Pquando disse -E, mas não sabia que era diferente.
Daenyth

3

Eu provavelmente faria uma pesquisa usando vimo :vimgrepcomando 's . Isso funciona de maneira vagamente semelhante à de, grepmas suporta REs e caminhos do vim.

Basicamente, você executa algo como :vimgrep 'pattern1\npattern2' path/**uma pesquisa recursiva e digita :copenpara abrir uma janela menor contendo uma lista de correspondências.

vimOs REs podem fazer quase tudo o que os PCREs podem, mas eles evoluíram separadamente da linhagem de expressão regular perl, de modo que a maioria das coisas avançadas funciona de maneira diferente. Sua funcionalidade básica é mais parecida com a dos REs básicos, mas eles têm algumas adições bacanas que os PCREs não oferecem.

Não tenho certeza se é possível :vimgrepcuspir dados como grepfaz; Eu só tentei usá-lo para navegação interna vim.

:help vimgrepde dentro vimpara mais informações; :help pattern.txtpara informações sobre vimREs; para mais informações sobre caminhos, consulte :help wildcards.


Tenha cuidado - isso não é inteiramente portátil como ele irá se comportar de forma diferente em diferentes plataformas
Daenyth

1
@ Daenyth: você quer dizer sob a influência de diferentes .vimrc? Deve ser mais portátil do que grepem relação ao sistema operacional: vimnão possui um "sabor POSIX" e funciona mais ou menos de forma idêntica, mesmo no Windows. .................................................. ........................... É possível adicionar qualificadores para garantir que, por exemplo, a quantidade certa de "mágica" seja usada no ER, embora Pelo que entendi, existe uma regra estrita e não escrita para deixar essa opção em paz.
intuited

Eu não o usei, mas aparentemente ele usa um back-end diferente no Windows (em find.exevez de grep). Houve outra pergunta nas últimas semanas que teve esse problema.
Daenyth

1
@ Daenyth: Você está pensando :vimgrepou :grep? De :help grep: "A vantagem do grep interno [ie :vimgrep] é que ele funciona em todos os sistemas e usa os poderosos padrões de pesquisa do Vim".
intuited

1
Ah, deve ser isso. Eu confundi os dois.
Daenyth

2

O Grep funciona apenas em uma linha de cada vez, mas você pode usar o awk para imprimir linhas que correspondam a vários padrões:

cat file | awk '/foo/,/bar/'

combinaria qualquer coisa, não apenas novas linhas entre os dois padrões


0

Para tirar o máximo proveito do unix, você precisa tirar proveito dos pipes. Você pode fazer isso de maneira simples grepusando tubos (sem necessidade de tee):

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

O que eu não consideraria tedioso.


Eu acho que isso é propenso a erros, pois entre pattern1 e pattern2 pode existir pattern3, que pode não ser o que você está procurando. Então você tem que controlar cada ocorrência manualmente.
math
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.