Y at-il un caractère générique véritablement universel dans Grep? [dupliquer]
Question
Cette question a déjà une réponse ici:
question vraiment fondamentale ici. Donc, je dis qu'un point. correspond à tout caractère sauf un saut de ligne. Je cherche quelque chose qui correspond à tout caractère, y compris les sauts de ligne.
Tout ce que je veux faire est de saisir tout le texte dans une page Web entre deux chaînes spécifiques, l'en-tête de décapage et le pied de page. Quelque chose comme TEXT HEADER (. +) TEXT puis extraire FOOTER ce qui est dans les parenthèses, mais je ne peux pas trouver un moyen d'inclure tous les sauts de texte et la ligne entre tête et pied de page, est-ce sens? Merci d'avance!
La solution
Quand je dois correspondre à plusieurs personnages, y compris les sauts de ligne, je fais:
[\s\S]*?
Note J'utilise un motif non gourmand
Autres conseils
Vous pouvez le faire avec Perl:
$ perl -ne 'print if /HEADER TEXT/ .. /FOOTER TEXT/' file.html
Pour imprimer uniquement le texte entre les délimiteurs, utilisez
$ perl -000 -lne 'print $1 while /HEADER TEXT(.+?)FOOTER TEXT/sg' file.html
Le commutateur /s
rend le matcher d'expression régulière traiter la chaîne entière comme s ligne Ingle, ce qui signifie point correspond à des sauts de ligne, et /g
signifie correspondre autant de fois que possible.
Les exemples ci-dessus supposent que vous êtes sur les fichiers de démarrage HTML sur le disque local. Si vous avez besoin de les chercher d'abord, utilisez get
de LWP::Simple
:
$ perl -MLWP::Simple -le '$_ = get "http://stackoverflow.com";
print $1 while m!<head>(.+?)</head>!sg'
S'il vous plaît noter que le HTML d'analyse syntaxique des expressions régulières comme ci-dessus ne fonctionne pas dans le cas général! Si vous travaillez sur un scanner rapide et sale, très bien, mais pour une application qui a besoin pour être plus robuste, utilisez un véritable analyseur.
Par définition, grep
recherche les lignes qui correspondance; il lit une ligne, voit si elle correspond, et imprime la ligne.
Une façon possible de faire ce que vous voulez est avec sed
:
sed -n '/HEADER TEXT/,/FOOTER TEXT/p' "$@"
Cette affiche de la première ligne qui correspond à « TEXT HEADER » à la première ligne qui correspond TEXT FOOTER ', puis itère; l'opération « -n » arrête la valeur par défaut 'imprimer chaque ligne. Cela ne fonctionne pas bien si le texte apparaît en-tête et pied de page sur la même ligne.
Pour faire ce que vous voulez, je serais probablement utiliser perl
(mais vous pouvez utiliser Python si vous préférez). Je considère siphonage le fichier entier, puis utiliser une expression régulière dûment qualifié pour trouver les parties correspondantes du fichier. Cependant, le Perl en une ligne donnée par « @gbacon » est une translittération presque exacte en Perl du script sed ci-dessus et est plus propre que siphonage.
La page de manuel de grep
dit:
grep, egrep, fgrep, rgrep - lignes d'impression correspondant à un motif
grep
est pas fait pour correspondre plus d'une seule ligne. Vous devriez essayer de résoudre cette tâche avec perl
ou awk
.
Comme cela est taggés avec « BBEdit » et supporte BBedit Pattern Perl Modificateurs-style vous pouvez autoriser le point pour correspondre avec le commutateur linebreaks (? S)
(? S).
correspond à tout caractère. Et oui, (? S). + correspondra à l'ensemble du texte.
Comme indiqué ailleurs, grep travaillera pour des trucs en ligne unique.
Pour plusieurs lignes (en rubis avec Regexp :: multiligne, ou en python, awk, sed, peu importe), "\ s" devrait également saisir les sauts de ligne, de sorte que
HEADER TEXT(.*\s*)FOOTER TEXT
pourrait fonctionner ...
Voici une façon de le faire avec gawk, si vous avez
awk -vRS="FOOTER" '/HEADER/{gsub(/.*HEADER/,"");print}' file