Grep ausgehend von einem festen Text bis zur ersten Leerzeile

9

Ich habe eine Datei prova.txtwie diese:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

extra1
extra2
bla

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

extra2
bla
bla

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

und ich muss von "Start to grab here" bis zur ersten leeren Zeile gehen. Die Ausgabe sollte folgendermaßen aussehen:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Wie Sie sehen können, sind die Zeilen nach "Start to grab here" zufällig, sodass das Grep-Flag -A-B nicht funktioniert:

cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt

Können Sie mir helfen, einen Weg zu finden, der die erste Zeile erfasst, die erfasst wird (als "Beginnen Sie von hier aus zu greifen"), bis eine leere Zeile angezeigt wird. Ich kann nicht vorhersagen, wie viele zufällige Zeilen ich nach "Beginnen Sie von hier aus zu greifen" haben werde.

Jede Unix-kompatible Lösung wird geschätzt (grep, sed, awk ist besser als Perl oder ähnliches).

EDITIERT: Nach einer brillanten Antwort von @ john1024 würde ich gerne wissen, ob es möglich ist:

1 ° sortiere den Block (nach Start von hier aus zu greifen: 1 dann 1 dann 2)

2 ° entferne 4 (alphabetisch zufällige) Zeilen fix1, fix2, fix3, fix4, aber immer 4

3 ° entfernen Sie schließlich zufällige Dupes, wie den Befehl sort -u

Die endgültige Ausgabe sollte folgendermaßen aussehen:

# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4

#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

oder

# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

Die zweite Ausgabe ist besser als die erste. Eine andere Unix-Befehlsmagie wird benötigt.

heisen
quelle
1
Dies ist sehr hilfreich, um den Stack-Trace für einen bestimmten Thread aus der Java-Jstack-Ausgabe abzurufen. Ich bin froh, dass ich diese Fragen und Antworten gefunden habe!
BenjaminBallard

Antworten:

13

Mit awk

Versuchen:

$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

/Start to grab/,/^$/definiert einen Bereich. Es beginnt mit jeder Zeile, die übereinstimmt, Start to grabund endet mit der ersten leeren Zeile ^$, die folgt.

Mit sed

Mit sehr ähnlicher Logik:

$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

-nfordert sed auf, nichts zu drucken, es sei denn, wir bitten ausdrücklich darum. /Start to grab/,/^$/pWeist es an, alle Zeilen in dem durch definierten Bereich zu drucken /Start to grab/,/^$/.

John1024
quelle
Ihre Lösung ist perfekt, ich habe meine Anfrage bearbeitet, um etwas hinzuzufügen. Schätzen Sie Ihre Hilfe. Vielen Dank
heisen
1

Ich poste eine alternative Lösung, da diese für einige Anwendungsfälle nützlich sein kann. Diese Lösung entspricht nicht genau den angegebenen Anforderungen. Die beste Lösung finden Sie in der Antwort von @ John1024.

Sie können awk verwenden, wenn der Datensatztrenner auf eine leere Zeichenfolge eingestellt ist. Awk interpretiert diese als leere Zeilenumbrüche:

$ awk '/Start/' RS= prova.txt 
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Diese Version behält die leeren Zeilenumbrüche in der Ausgabe nicht bei. Es wird auch der Kontext vor dem Spiel angezeigt, falls vorhanden. Dieses Verhalten kann sehr nützlich sein, wenn Sie nach etwas in einer Datei suchen und den durch Zeilenumbrüche getrennten Block sehen möchten, zu dem es gehört, zum Beispiel:

$ awk '/random1546/' RS= prova.txt 
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Zum Beispiel finde ich das nützlich, wenn ich nach Dingen in iniDateien suche .

htaccess
quelle