So extrahieren Sie einen Textabschnitt aus einer Datei zwischen übereinstimmenden Bedingungen

So extrahieren Sie einen Textabschnitt aus einer Datei zwischen übereinstimmenden Bedingungen

Ich habe eine Datei wie unten.

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

~PAR2~
This is Par2 line 1
This is Par2 line 2

Par Finished

Wenn ich übergebe , sollte ich alle Zeilen zwischen und Zeile PAR1erhalten . Wie kann ich das erreichen? Ich habe nach und gesucht und konnte keine Optionen finden.PAR1Par Finishedawksed

Antwort1

Wenn Sie die Kopf- und Fußzeile möchten, dann ist es ziemlich einfach mit sed zB

sed -n "/^~PAR1~$/,/Par Finished/p"

Dies ist einfach mit einer Variablen zu verwenden

START=PAR1
sed -n "/^~$START~$/,/Par Finished/p"

Wir können die letzte Zeile auch zu einer Variablen machen

START=PAR1
END="Par Finished"
sed -n "/^~$START~$/,/$END/p"

Das Ergebnis sieht wie folgt aus:

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Wenn Sie weder Start-/Endzeilen noch Leerzeilen möchten, ist die Sache etwas komplizierter.

Es gibt vielleicht bessere Möglichkeiten, aber das hier funktioniert bei mir:

sed -n "/^~$START~$/,/$END/ { /^~$START~$/d ; /$END/d ; /^$/d ; p }"

Das Ergebnis davon ist

This is Par1 line 1
This is Par1 line 2

Antwort2

Par FinishedSie können die Zeile (mit optionalen nachfolgenden Leerzeilen) als Datensatztrennzeichen verwenden (und sie dann ersetzen, um den Datensatz zu vervollständigen).

awk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {print $0,"\nPar Finished"}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Wenn Sie über GNUawk verfügen, können Sie den Datensatztrenner mit der speziellen Variable wiederherstellen RT(und dabei die zusätzlichen Zeilenumbrüche entfernen, wenn Sie möchten).

gawk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {sub("\n*$", "", RT); print $0,RT}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Natürlich, wenn Sie nicht passieren müssen eineVariable Par1Sie verwenden einen einfachen Regex-Bereich

awk '/PAR1/,/Par Finished/' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Antwort3

Mit grepund pcrefür ausreichend kleine Dateieingaben

$ s="PAR1"

$ grep -oPz "(?s)[^\n]*${s}.*?\n.*?Par Finished.*?\n" ip.txt 
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

So erhalten Sie Linien zwischen den Mustern:

$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par beendet)" ip.txt
Dies ist Par1 Zeile 1
Dies ist Par1 Zeile 2

Variable ändern inPAR2

$ s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par beendet)" ip.txt
Dies ist Par2 Linie 1
Dies ist Par2 Linie 2

Referenz: Regex (grep) für mehrzeilige Suche

verwandte Informationen