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 \Knotifier au lieu de l'assertion Lookbehind.
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
\Koption ignore tout avant la correspondance de motifs et ignore le motif lui-même.
\nutilisé 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)" filepour ne pas imprimer le \ncaractè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ütztLa traduction de l'erreur est quelque chose comme:grep: a not protected ^ or $ is not supported with -Pz
grepsemble avoir changé.
Dans le cas où votre grepne 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