Pour être précis
Some text
begin
Some text goes here.
end
Some more text
et je veux extraire le bloc entier qui commence du "début" à la "fin".
avec awk on peut faire comme awk '/begin/,/end/' text
.
Comment faire avec grep?
Pour être précis
Some text
begin
Some text goes here.
end
Some more text
et je veux extraire le bloc entier qui commence du "début" à la "fin".
avec awk on peut faire comme awk '/begin/,/end/' text
.
Comment faire avec grep?
Réponses:
Mis à jour le 18 novembre 2016 (puisque le comportement de grep est modifié: grep avec le paramètre -P ne prend plus en charge ^
et $
ancre [sur Ubuntu 16.04 avec le noyau v: 4.4.0-21-generic]) (correct (non) correct )
$ grep -Pzo "begin(.|\n)*\nend" file
begin
Some text goes here.
end
Remarque: pour les autres commandes, remplacez simplement les ancres '^' et '$' par une ancre de nouvelle ligne '\n'
______________________________
Avec la commande grep:
grep -Pzo "^begin\$(.|\n)*^end$" file
Si vous ne voulez pas inclure les modèles "begin" et "end" dans le résultat, utilisez grep avec le support de Lookbehind et Lookahead.
grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file
Vous pouvez également utiliser \K
notifier au lieu de l'assertion Lookbehind.
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
\K
option ignore tout avant la correspondance de motifs 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 un simple grep facile 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 blanc.
Et leur sortie sans inclure "début" et "fin" 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 ( obsolète car le comportement de grep avec le paramètre -P est modifié )
^
pointez le début d'une ligne et $
pointez la fin d'une ligne. ceux-ci s'ajoutent aux alentours de "début" et "fin" pour les faire correspondre s'ils sont seuls dans une ligne.
Dans deux commandes, je me suis é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.
grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" file
pour ne pas imprimer le \n
caractère qui existe sur la ligne commence.
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
La traduction de l'erreur est quelque chose comme:grep: a not protected ^ or $ is not supported with -Pz
grep
semble avoir changé.
Dans le cas où votre grep
ne prend pas en charge la syntaxe perl ( -P
), vous pouvez essayer de joindre les lignes, de faire correspondre le modèle, puis de développer à nouveau les lignes comme ci-dessous:
$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end