2009-12-13 10 views
6

Wirklich grundlegende Frage hier. Also mir wurde gesagt, dass ein Punkt. passt auf jedes Zeichen außer einem Zeilenumbruch. Ich suche nach etwas, das zu jedem Charakter passt, einschließlich Zeilenumbrüchen.Gibt es in Grep eine wirklich universelle Wildcard?

Alles, was ich tun möchte, ist den gesamten Text in einer Website-Seite zwischen zwei bestimmten Zeichenfolgen zu erfassen, die Kopfzeile und die Fußzeile strippen. Etwas wie HEADER TEXT (. +) FOOTER TEXT und dann extrahieren, was in den Klammern ist, aber ich finde keine Möglichkeit, alle Text UND Zeilenumbrüche zwischen Kopf- und Fußzeile aufzunehmen, macht das Sinn? Danke im Voraus!

Antwort

7

Wenn ich mehrere Zeichen übereinstimmen müssen, einschließlich der Zeilenumbrüche, ich mache:

[\s\S]*? 

Hinweis Ich bin mit einem nicht-gierigen Muster

+2

Danke Jungs! Was für eine freundliche, nützliche Seite. Ich habe vergessen zu erwähnen, dass ich die grep-Suche in BBEdit verwendet habe, das funktioniert wunderbar. Sie alle rocken! –

3

Man könnte es mit Perl tun:

$ perl -ne 'print if /HEADER TEXT/ .. /FOOTER TEXT/' file.html 

Um nur den Text zwischen den Trennzeichen zu drucken, verwendet

$ perl -000 -lne 'print $1 while /HEADER TEXT(.+?)FOOTER TEXT/sg' file.html 

Der /s Schalter macht die reguläre Ausdruck Matcher die gesamte Zeichenfolge als behandeln s Eine Zeile, was bedeutet, dass der Punkt mit Zeilenumbrüchen übereinstimmt, und /g bedeutet, dass Sie so oft wie möglich übereinstimmen.

Die obigen Beispiele gehen davon aus, dass Sie HTML-Dateien auf der lokalen Festplatte starten. Wenn man sie braucht zuerst zu holen, verwenden get von LWP::Simple:

$ perl -MLWP::Simple -le '$_ = get "http://stackoverflow.com"; 
          print $1 while m!<head>(.+?)</head>!sg' 

Bitte beachten Sie, dass Parsing HTML mit regulären Ausdrücken wie oben nicht im allgemeinen Fall nicht funktioniert! Wenn Sie an einem schnellen Scanner arbeiten, sollten Sie einen echten Parser verwenden, aber für eine Anwendung, die robuster sein muss.

1

Wie bereits an anderer Stelle erwähnt, funktioniert grep auch für Single-Line-Dateien.

Bei Mehrlinien (in Ruby mit Regexp :: mehrzeilige oder in Python, awk, sed, was auch immer), "\ s" sollte auch Zeilenumbrüche erfassen, so

HEADER TEXT(.*\s*)FOOTER TEXT 

arbeiten könnte .. .

+0

Sie müssten die Datei in einem Modus lesen, der mehrere Zeilen in den Speicher scannt, damit das funktioniert. –

+0

Danke, ich habe hinzugefügt, wie Sie das in Ruby machen würden. IIRC, das ist in Perl, oder? – phtrivier

2

der Mann Seite von grep sagt:

grep, egrep, fgrep, rgrep - Druckzeilen mit einem Muster übereinstimmen

grep ist nicht für die Zuordnung von mehr als einer einzelnen Zeile vorgesehen. Sie sollten versuchen, diese Aufgabe mit perl oder awk zu lösen.

3

Per Definition sucht grep nach Zeilen, die übereinstimmen; Es liest eine Zeile, sieht, ob es übereinstimmt, und druckt die Zeile.

Ein möglicher Weg, was Sie tun wollen, ist mit sed:

sed -n '/HEADER TEXT/,/FOOTER TEXT/p' "[email protected]" 

Diese Drucke von der ersten Zeile, die ‚Kopftext‘ auf der ersten Zeile entspricht, die ‚Fußzeilentext‘ übereinstimmt, und iteriert dann; Die Option '-n' stoppt die Standardaktion 'Jede Zeile drucken'. Dies funktioniert nicht gut, wenn der Kopf- und Fußzeilentext in derselben Zeile erscheint.

Um zu tun, was Sie wollen, würde ich wahrscheinlich perl verwenden (aber Sie könnten Python verwenden, wenn Sie bevorzugen). Ich würde in Betracht ziehen, die ganze Datei zu schlürfen und dann einen entsprechend qualifizierten Regex zu verwenden, um die passenden Teile der Datei zu finden. Der Perl-Einzeiler von '@gbacon' ist jedoch eine fast exakte Transliteration in Perl der obigen 'sed'-Schrift und ist ordentlicher als schlürfen.

0

hier kann man es mit gawk zu tun, wenn Sie haben es

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

Da dies mit ‚BBEdit‘ markiert ist und BBedit unterstützt Perl-Art-Muster-Modifikatoren Sie der Punkt Zeilenumbrüche erlauben kann mit dem Schalter übereinstimmen (? s)

(? S).

wird mit jedem Zeichen übereinstimmen. Und ja, (? S). + wird mit dem gesamten Text übereinstimmen.