Para ser mais preciso
Some text
begin
Some text goes here.
end
Some more text
e eu quero extrair um bloco inteiro que começa de "begin" até "end".
com awk podemos fazer o mesmo awk '/begin/,/end/' text
.
Como fazer com grep?
Para ser mais preciso
Some text
begin
Some text goes here.
end
Some more text
e eu quero extrair um bloco inteiro que começa de "begin" até "end".
com awk podemos fazer o mesmo awk '/begin/,/end/' text
.
Como fazer com grep?
Respostas:
Atualizado 18 de novembro de 2016 (como o comportamento do grep foi alterado: o parâmetro grep com -P agora não suporta ^
e $
ancora [no Ubuntu 16.04 com kernel v: 4.4.0-21-generic]) ( correção incorreta (não) )
$ grep -Pzo "begin(.|\n)*\nend" file
begin
Some text goes here.
end
nota: para outros comandos, substitua as âncoras '^' e '$' pela âncora de nova linha '\n'
______________________________
Com o comando grep:
grep -Pzo "^begin\$(.|\n)*^end$" file
Se você quiser não incluir os padrões "begin" e "end" no resultado, use grep com o suporte Lookbehind e Lookahead.
grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file
Além disso, você pode usar a \K
notificação notificar, em vez da asserção Lookbehind.
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
\K
A opção ignora tudo antes da correspondência de padrões e ignora o próprio padrão.
\n
usado para evitar a impressão de linhas vazias na saída.
Ou como @AvinashRaj sugere que há grep fácil e simples como a seguir:
grep -Pzo "(?s)^begin$.*?^end$" file
grep -Pzo "^begin\$[\s\S]*?^end$" file
(?s)
diz ao grep para permitir que o ponto corresponda a caracteres de nova linha.
[\s\S]
corresponde a qualquer caractere que seja espaço em branco ou não em branco.
E a saída deles sem incluir "begin" e "end" é a seguinte:
grep -Pzo "^begin$\n\K[\s\S]*?(?=\n^end$)" file # or grep -Pzo "(?<=^begin$\n)[\s\S]*?(?=\n^end$)"
grep -Pzo "(?s)(?<=^begin$\n).*?(?=\n^end$)" file
veja aqui o teste completo de todos os comandos ( fora de datado, pois o comportamento grep com o parâmetro -P é alterado )
^
aponte o início de uma linha e $
aponte o final de uma linha. estes foram adicionados ao redor de "begin" e "end" para combiná-los se estiverem sozinhos em uma linha.
Em dois comandos, escapei $
porque ele também usava para "Substituição de Comando" ( $(command)
) que permite que a saída de um comando substitua o nome do comando.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
-P, --perl-regexp
Interpret PATTERN as a Perl compatible regular expression (PCRE)
-z, --null-data
Treat the input as a set of lines, each terminated by a zero byte (the ASCII
NUL character) instead of a newline. Like the -Z or --null option, this option
can be used with commands like sort -z to process arbitrary file names.
grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" file
para não imprimir o \n
caractere existente na linha de início.
grep -Pzo "(?s)begin.*?end" file
grep -Pzo "begin[\s\S]*?end" file
grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstützt
A tradução do erro é algo como:grep: a not protected ^ or $ is not supported with -Pz
grep
parece ter mudado.