web-dev-qa-db-de.com

Wie kann ich in einer Datei nach einem mehrzeiligen Muster suchen?

Ich musste alle Dateien finden, die ein bestimmtes Zeichenkettenmuster enthielten. Die erste Lösung, die mir einfällt, ist die Verwendung von find piped mit xargs grep :

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'

Wenn ich jedoch Muster finden muss, die sich über mehr als eine Zeile erstrecken, stecke ich fest, weil Vanilla Grep keine Mehrfachmuster finden kann.

104
Oli

Also entdeckte ich pcregrep , was für Perl Compatible Regular Expressions GREP steht.

Sie müssen beispielsweise nach Dateien suchen, bei denen die Variable '_name' unmittelbar gefolgt von der Variablen '_description' folgt:

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'

Tipp: Sie müssen das Zeilenumbruchzeichen in Ihr Muster einfügen. Je nach Plattform kann es sich um '\ n',\r ','\r\n ', ... handeln.

92
Oli

Warum gehst du nicht nach awk :

awk '/Start pattern/,/End pattern/' filename
81
Amit

Hier ist das Beispiel mit GNU grep :

grep -Pzo '_name.*\n.*_description'

-z/--null-data Behandle Eingabe- und Ausgabedaten als Zeilenfolgen.

Siehe auch hier

65
ayaz

grep -P verwendet ebenfalls libpcre, ist jedoch much breiter installiert. Um einen vollständigen title-Abschnitt eines HTML-Dokuments zu finden, auch wenn es mehrere Zeilen umfasst, können Sie Folgendes verwenden:

grep -P '(?s)<title>.*</title>' example.html

Da das PCRE-Projekt den Perl-Standard implementiert, verwenden Sie die Perl-Dokumentation als Referenz:

20
bukzor

Hier ist ein nützlicheres Beispiel:

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html

Es durchsucht das Titel-Tag in einer HTML-Datei, auch wenn es bis zu 5 Zeilen umfasst.

Hier ist ein Beispiel für unbegrenzte Zeilen:

pcregrep -Mi "(?s)<title>.*</title>" example.html 
14
Oli

Mit Silber Sucher :

ag 'abc.*(\n|.)*efg'

Hier könnten möglicherweise Geschwindigkeitsoptimierungen des Silber-Suchers erscheinen.

7
Shwaydogg

Sie können die grep-Alternative sift hier verwenden (Haftungsausschluss: Ich bin der Autor).

Es unterstützt den mehrzeiligen Abgleich und beschränkt die Suche auf bestimmte Dateitypen:

sift -m --files '* .py' 'YOUR_PATTERN'

(Alle * .py-Dateien nach dem angegebenen mehrzeiligen Regex-Muster durchsuchen.)

Es ist für alle gängigen Betriebssysteme verfügbar. Werfen Sie einen Blick auf die Seite samples , um zu erfahren, wie Sie damit mehrseitige Werte aus einer XML-Datei extrahieren können.

4
svent

Diese Antwort könnte nützlich sein:

Regex (grep) für mehrzeilige Suche erforderlich

Um rekursiv zu suchen, können Sie die Flags -R (rekursiv) und --include (GLOB-Muster) verwenden. Sehen:

Use grep --exclude/- include-Syntax, um bestimmte Dateien nicht durchzugehen

3
albfan
Perl -ne 'print if (/begin pattern/../end pattern/)' filename
2
pbal

Verwendung von ex/vi editor und globstar Option (Syntax ähnlich awk und sed)

ex +"/string1/,/string3/p" -R -scq! file.txt

dabei ist aaa Ihr Startpunkt und bbb Ihr Endetext.

Um rekursiv zu suchen, versuchen Sie Folgendes:

ex +"/aaa/,/bbb/p" -scq! **/*.py

Hinweis: Um die **-Syntax zu aktivieren, führen Sie shopt -s globstar (Bash 4 oder zsh) aus.

1
kenorb

@Marcin: Awk Beispiel nicht gierig:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename
0
Martin