Grep mehrzeiliges Muster

13

Wie suche ich über mehrere Zeilen nach einer Phrase? ZB Lets haben die Phrase "mein Eistee", dann kann es in Textdateien eingewickelt werden:

as js skdfh dfh djh sf my
ice tea.

grep stimmt nicht überein, da dazwischen ein Zeilenumbruch steht. Wie passe ich diese an? Ein weiteres mehrzeiliges Muster wärepattern1_\n_pattern2

Ich weiß, dass der einfachste Weg, wie ich Geldautomaten mache, darin besteht, nur einen Teil zu greifen, z. Das ist aber sehr mühsam. Ich bin also interessiert, wie Sie das lösen könnten.

Mathematik
quelle
1
Mögliche Cross-Site-Duplikate von: stackoverflow.com/questions/152708/…
Ciro Santilli

Antworten:

16

Sie könnten installieren pcregrep(in den meisten Distributions-Repositories verfügbar) - was grep unter Verwendung der pcre-Bibliothek ist , die "Perl-kompatible reguläre Ausdrücke" ausführt . Es verfügt über eine Befehlszeilenoption, mit -Mder Sie mehrzeilige Suchen durchführen können - über die Manpage :

"Die Ausgabe für eine Übereinstimmung kann aus mehr als einer Zeile bestehen."

Also könntest du tun

pcregrep -M 'my\s+ice\s+tea' filename

Das \sist Leerzeichen, das wird passen \nund \rin mehrzeiligen Modus, zusätzlich zu den normalen Leerzeichen. Sie können das Zeilenumbruchzeichen auch direkt abgleichen

pcregrep -M 'pattern1_\n_pattern2' filename
Hamish Downer
quelle
+1 schön. Ich habe noch nie davon gehört, aber ich habe es ausprobiert und es funktioniert wie ein Zauber!
DaveParillo
Tut grep -Epcre Muster nicht?
Daenyth
3
@Daenyth grep -E meist nur bedeutet , können Sie verwenden ?, +, {, |, (, und )als ihre übliche regex Bedeutung ohne eine haben, die \ vor, wie Sie tun , wenn Sie Standard grep verwenden. Ist grep 'hello\s\+world' filealso gleichbedeutend mit grep -E 'hello\s+world' file. PCRE funktioniert nicht. Es gibt grep -Pfür Perl reguläre Ausdrücke, aber es ist experimentell (gemäß der Manpage) und ich denke, es ist ein wenig anders als pcregrep ...
Hamish Downer
1
Ja, ich habe darüber nachgedacht, -Pals ich sagte -E, aber ich habe nicht bemerkt, dass es anders ist.
Daenyth
3

Ich würde wahrscheinlich eine Suche mit vim's :vimgrepBefehl durchführen. Dies funktioniert auf eine Art und Weise, die der von grepREs und Pfaden vage ähnlich ist, diese aber unterstützt.

Grundsätzlich führen Sie so etwas wie :vimgrep 'pattern1\npattern2' path/**eine rekursive Suche aus und :copenrufen dann ein kleineres Fenster mit einer Liste von Übereinstimmungen auf.

vimREs können fast alles, was PCREs können, aber sie haben sich unabhängig von der Perl-Linie der regulären Ausdrücke entwickelt, sodass die meisten fortgeschrittenen Dinge anders funktionieren. Ihre Grundfunktionalität ähnelt eher der von grundlegenden REs, aber sie haben einige raffinierte Ergänzungen, die PCREs nicht bieten.

Ich bin nicht sicher, ob es möglich ist :vimgrep, Daten so auszuspucken, wie es der grepFall ist. Ich habe immer nur versucht, es für die Navigation innerhalb zu verwenden vim.

:help vimgrepvon innen vimfür mehr Infos; :help pattern.txtfür Informationen zu vimREs; Weitere Informationen zu Pfaden finden Sie unter :help wildcards.

intuitiert
quelle
Seien Sie vorsichtig - das ist nicht ganz portabel, da es sich auf verschiedenen Plattformen unterschiedlich verhält
Daenyth,
1
@Daenyth: meinst du unter dem einfluss von anderen .vimrc? Es sollte portabler sein als grepin Bezug auf das Betriebssystem: Es vimhat keine "POSIX-Variante" und funktioniert auch unter Windows mehr oder weniger identisch. .................................................. ........................... Es ist jedoch möglich, Qualifikationsmerkmale hinzuzufügen, um sicherzustellen, dass z. B. die richtige Menge an "Magie" in der RE verwendet wird Soweit ich weiß, gibt es eine strenge ungeschriebene Regel, um diese Option in Ruhe zu lassen.
Intuited
Ich habe es selbst nicht benutzt, aber anscheinend benutzt es ein anderes Backend für Windows ( find.exeanstelle von grep). In den letzten Wochen gab es eine andere Frage, die dieses Problem hatte.
Daenyth
1
@Daenyth: Denkst du an :vimgrepoder :grep? Von :help grep: "Der Vorteil des internen grep [ie :vimgrep] ist, dass es auf allen Systemen funktioniert und die leistungsstarken Vim-Suchmuster verwendet."
Intuited
1
Ah, das muss es sein. Ich habe die beiden verwirrt.
Daenyth
2

Grep funktioniert jeweils nur in einer Zeile, aber Sie können awk verwenden, um Zeilen zu drucken, die mit einer Reihe von Mustern übereinstimmen:

cat file | awk '/foo/,/bar/'

es würde alles zusammenpassen, nicht nur Zeilenumbrüche zwischen den beiden Mustern

DaveParillo
quelle
0

Um das Beste aus Unix herauszuholen, müssen Sie die Vorteile von Pipes nutzen. Sie können dies in einfachen grepRohren tun (kein Abschlag erforderlich):

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

Was ich nicht als mühsam empfinde.

Baruch
quelle
Ich denke, das ist fehleranfällig, da zwischen Muster1 und Muster2 Muster3 existieren können, die möglicherweise nicht das sind, wonach Sie suchen. Sie müssen also jeden Treffer manuell steuern.
Mathe