Pour être précis
Some text
begin
Some text goes here.
end
Some more text
et je veux extraire tout le bloc qui commence par "begin" jusqu'à "end".
avec awk nous pouvons faire comme awk '/begin/,/end/' text
.
Comment faire avec grep?
Mise à jour le 18 nov. 2016 (le comportement de grep ayant été modifié: grep avec le paramètre -P ne prend désormais plus en charge les ancres ^
et $
[sous Ubuntu 16.04 avec noyau v: 4.4.0-21-generic]) ( correctif (non) correct) )
$ grep -Pzo "begin(.|\n)*\nend" file
begin
Some text goes here.
end
remarque: pour les autres commandes, il suffit de remplacer les ancres '^' et '$' par des ancres new-line '\n'
______________________________
Avec la commande grep:
grep -Pzo "^begin\$(.|\n)*^end$" file
Si vous souhaitez ne pas inclure les modèles "begin" et "end" dans le résultat, utilisez grep avec le support Lookbehind et Lookahead.
grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file
Vous pouvez également utiliser \K
notify au lieu de l'assertion Lookbehind.
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
L'option \K
ignore tout ce qui se trouve avant le filtrage du motif et ignore le motif lui-même.\n
utilisé pour éviter d’imprimer des lignes vides à partir de la sortie.
Ou, comme @AvinashRaj le suggère, il existe de simples grep faciles comme suit:
grep -Pzo "(?s)^begin$.*?^end$" file
grep -Pzo "^begin\$[\s\S]*?^end$" file
(?s)
indique à grep d'autoriser le point à correspondre aux caractères de nouvelle ligne.[\s\S]
correspond à tout caractère blanc ou non.
Et leur sortie sans inclure "begin" et "end" est la suivante:
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
voir le test complet de toutes les commandes ici (le comportement de grep avec le paramètre -P n'est plus daté)
^
pointe le début d'une ligne et $
pointe la fin d'une ligne. ceux-ci sont ajoutés aux environs de "commencer" et "fin" pour les faire correspondre s'ils sont seuls dans une ligne.
Dans deux commandes, j’ai échappé à $
car il utilise également pour "Substitution de commande" ($(command)
) qui permet à la sortie d’une commande de remplacer le nom de la commande.
-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.
Si votre grep
ne prend pas en charge la syntaxe Perl (-P
), vous pouvez essayer de joindre les lignes, en faisant correspondre le modèle, puis en les développant à nouveau comme suit:
$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end