it-swarm.com.de

Wie kann ich den grep after context auf "bis zur nächsten leeren Zeile" setzen?

Mit grep weiß ich, wie man den Kontext auf eine feste Anzahl von Zeilen setzt. Ist es möglich, einen Kontext basierend auf einer beliebigen Zeichenfolgenbedingung anzuzeigen, z. B. Nachkontext auf "bis zur nächsten Leerzeile" setzen?

Oder möglicherweise eine andere Kombination von Werkzeugen?

Grundsätzlich habe ich eine Protokolldatei mit zusammenhängenden Zeilen, wobei Leerzeilen die "Ereignisse" trennen, die ich in der Protokolldatei nach einem String suchen möchte, aber das gesamte Ereignis anzeigen ....

30
pixelearth

Es klingt, als ob Sie sed brauchen:

sed -n '/pattern/,/^$/p' file

Nicht standardmäßig drucken (-n). Drucken Sie für Zeilen, die mit /pattern/ bis zu einer leeren Zeile /^$/ übereinstimmen.

28

Eine einfache Lösung ist:

awk '/pattern/' RS= input-file

Wenn Sie RS auf die leere Zeichenfolge setzen, behandelt awk leere Zeilen als Datensatztrennzeichen, und die einfache Regel /pattern/ bewirkt, dass awk jeden Datensatz druckt, der dem Muster entspricht. Dies kann ein beliebiger erweiterter regulärer Ausdruck sein.

20
William Pursell

Hier ist eine (getestete) awk-Lösung, die zur besseren Lesbarkeit auf mehrere Zeilen aufgeteilt ist:

awk '/pattern/ {do_print=1}
     do_print==1 {print}  
     NF==0 {do_print=0}' input_file

Dieses Skript druckt auch die leere Zeile, so dass es einfacher ist, die verschiedenen übereinstimmenden Blöcke visuell zu trennen. Wenn Sie die leere Zeile nicht möchten, tauschen Sie die beiden Zeilen do_print==1 {print} und NF==0 {do_print=0} aus.

Erklärung:

  • awk: Ruft das awk-Tool auf - es wertet die Eingabe Zeile für Zeile nacheinander aus.
  • '...'.: Alles, was in den einfachen Anführungszeichen steht, wird awk als Anweisungen gegeben. In diesem Fall führen wir die angegebenen Anweisungen in jeder Zeile durch.
  • /pattern/ {do_print=1}: Wenn eine Zeile "pattern" enthält, aktivieren Sie das Flag do_print
  • do_print==1 {print}: Wenn das Flag do_print aktiviert ist, wird die aktuelle Zeile gedruckt.
  • NF==0 {do_print=0}: NF steht für Number of Fields. awk begrenzt jede Zeile standardmäßig durch Leerzeichen und Tabulatoren, um eine Zeile in Felder aufzuteilen. In diesem Fall hat eine leere Zeile trivialerweise keine Felder - daher deaktivieren wir das Flag do_print, um den Druckvorgang zu stoppen, wenn eine Zeile mit NF == 0 angezeigt wird.
8
sampson-chen

Persönlich gefällt mir die Antwort von @William Pursell, da der Vorher-Kontext oft nützlich ist (z. B. beim Suchen nach Dingen in ini-Dateien). Wenn Sie eigentlich nur den After-Kontext mit awk wünschen, können Sie Folgendes tun:

$ cat demo.ini 
[foo]
aaa = 1
bbb = 2
ccc = 3

[bar]
eee = 8
fff = 0
ggg = 1

[baz]
xxx = 1
yyy = 0
zzz = 2
$ awk '/bar/,/^$/' demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1

$ awk '/fff/,/^$/' demo.ini 
fff = 0
ggg = 1

$

Vergleiche mit der RS= Version:

$ awk '/bar/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
0
htaccess