2009-12-13 14 views
6

Question vraiment fondamentale ici. Donc on me dit qu'un point. correspond à n'importe quel caractère SAUF un saut de ligne. Je cherche quelque chose qui correspond à n'importe quel personnage, y compris les sauts de ligne.Existe-t-il un caractère générique vraiment universel dans Grep?

Tout ce que je veux faire est de capturer tout le texte dans une page de site Web entre deux chaînes spécifiques, dépouillant l'en-tête et le pied de page. Quelque chose comme TEXTE EN CHEF (. +) FOOTER TEXT puis extraire ce qui est dans les parenthèses, mais je ne peux pas trouver un moyen d'inclure tout le texte et les sauts de ligne entre en-tête et pied de page, est-ce logique? Merci d'avance!

Répondre

7

Quand je dois correspondre à plusieurs personnages, y compris les sauts de ligne, je fais:

[\s\S]*? 

Remarque J'utilise un motif non gourmand

+2

Merci les gars! Quel site convivial et utile. J'ai oublié de mentionner que j'utilisais la recherche grep dans BBEdit, cela fonctionne à merveille. Vous êtes tous rock! –

3

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 en ligne, ce qui signifie que le point correspond à de nouvelles lignes, et /g signifie correspondre autant de fois que possible.

Les exemples ci-dessus supposent que vous utilisez des fichiers HTML sur le disque local. Si vous avez besoin de les chercher d'abord, utiliser 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 doit être plus robuste, utilisez un vrai analyseur.

1

Comme indiqué ailleurs, grep fonctionnera pour les choses sur une seule ligne.

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

HEADER TEXT(.*\s*)FOOTER TEXT 

pourrait fonctionner .. .

+0

Vous devriez lire le fichier dans un mode qui scanne plusieurs lignes en mémoire pour que cela fonctionne. –

+0

Merci, j'ai ajouté comment vous le feriez dans Ruby. IIRC, c'est en perlish, n'est-ce pas? – phtrivier

2

La page de manuel de grep dit:

grep, egrep, fgrep, rgrep - lignes d'impression correspondant à un motif

grep n'est pas faite pour faire correspondre plus d'une seule ligne. Vous devriez essayer de résoudre cette tâche avec perl ou awk.

3

Par définition, grep recherche les lignes qui correspondent; il lit une ligne, voit s'il 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' "[email protected]" 

Cette impression de la première ligne qui correspond à « TEXT HEADER » à la première ligne qui correspond à « FOOTER TEXT », puis itère; le '-n' arrête l'opération 'imprimer chaque ligne' par défaut. Cela ne fonctionnera pas bien si le texte d'en-tête et de pied de page apparaît sur la même ligne.Pour faire ce que vous voulez, j'utiliserais probablement perl (mais vous pouvez utiliser Python si vous préférez). Je considèrerais le slurping de l'ensemble du fichier, puis utiliser une regex qualifié pour trouver les parties correspondantes du fichier. Cependant, le doublage Perl donné par '@ gbacon' est une translittération presque exacte en Perl du script 'sed' ci-dessus et est plus propre que le slurping.

0

est ici une façon de le faire avec gawk, si vous l'avez

awk -vRS="FOOTER" '/HEADER/{gsub(/.*HEADER/,"");print}' file 
2

Comme il est marqué avec « BBEdit » et BBedit soutient Pattern Perl Modificateurs-style vous pouvez autoriser le point pour correspondre avec le commutateur linebreaks (? s)

(? S).

correspond à n'importe quel caractère. Et oui, (? S). + correspondra au texte entier.