@ warl0ck me apontou na direção certa com pcregrep
, mas eu disse "contém", não "é", e eu perguntei sobre um diretório, não um arquivo.
Isso parece funcionar para mim.
pcregrep -rMi 'Foo(.*)\n(.*)Bar' .
Como posso grep um diretório para linhas que contêm "Foo", mas somente obtém correspondências quando a próxima linha também contém "Barra"?
@ warl0ck me apontou na direção certa com pcregrep
, mas eu disse "contém", não "é", e eu perguntei sobre um diretório, não um arquivo.
Isso parece funcionar para mim.
pcregrep -rMi 'Foo(.*)\n(.*)Bar' .
O próprio Grep parece não suportar, use o pcregrep em vez disso:
Foo
Bar
Foo
abc
pcregrep -M "Foo\nBar" file
Tem:
Foo
Bar
Com um script sed
:
#!/bin/sed -nf
/^Foo/{
h # put the matching line in the hold buffer
n # going to nextline
/^Bar/{ # matching pattern in newline
H # add the line to the hold buffer
x # return the entire paragraph into the pattern space
p # print the pattern space
q # quit the script now
}
}
Para usá-lo:
chmod +x script.sed
printf '%s\n' * | ./script.sed
O printf
aqui exibe todos os arquivos no diretório atual em uma linha cada, e passa para sed
.
Nota : esta é ordenada por ordem alfabética.
Mais informações sobre pattern space
e hold space
úteis AQUI .
grymoire.com tem coisas realmente boas sobre shell
programação.
Usando apenas grep
, você pode construir o seguinte canal:
grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'
O primeiro grep
obterá todas as linhas que contêm Foo
, bem como a linha após a correspondência. Em seguida, obtemos linhas que contêm Bar
, bem como a linha antes da correspondência e, finalmente, extrair as linhas dessa saída que contêm Foo
.
EDITAR: Como manatwork apontou, existem alguns casos problemáticos a serem observador de. Apesar de ser um desafio interessante, devido à funcionalidade orientada a linha de grep
, qualquer solução com ele provavelmente é um 'hack' e você provavelmente está melhor usando algo como pcregrep
que é mais adequado para a tarefa em questão.
Embora eu prefira a solução de Nathan usando pcregrep
, aqui está a solução usando apenas o grep
grep -o -z -P 'Foo(.*)\n(.*)Bar' file
Explicação das opções:
-o
imprime apenas a parte correspondente. Necessário já que a inclusão de -z
imprimirá todo o arquivo (a menos que haja um \ 0 em algum lugar) -z
Trate a entrada como um conjunto de linhas, cada uma terminada por um zero
byte (o caractere ASCII NUL) em vez de uma nova linha. -P
perl sintaxe regex EDIT: Esta versão imprime linhas inteiras combinadas
grep -o -P -z '(.*)Foo(.*)\n(.*)Bar(.*)' file
com o awk:
awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
/foo/ {prev=$0; next}
{prev=""}' file1...
(nota geral sobre a limitação do awk: cuidado para que, se alguns nomes de arquivos contiverem caracteres "=", você precisará passá-los como ./filename
em vez de filename
para awk)
Tags grep regular-expression