Ich möchte in einer bestimmten Datei nach einer bestimmten Zeichenfolge suchen. Wenn ich die Zeichenfolge gefunden habe, möchte ich auch die Zeilen der Zeile X vor (oder nach) dieser Zeile drucken.
Kann das mit grep oder awk oder brauche ich eine Kombination?
Ich möchte so etwas wie haben , diese aber nicht mit allen Hinter / führenden Linien vor oder nach einem Treffer, nur der X - te.
Zum Beispiel, wenn meine Eingabe so aussieht:
line1 with a pattern
line2
line3
line4 with a pattern
line5
line6
line7 with a pattern
...
Ich möchte zB nach dem Wort 'Muster' suchen und diese Zeile + die Zeile ausgeben, die 2 Zeilen danach ist, aber nicht die Zeile, die direkt auf die Zeile mit dem Muster folgt. Die gewünschte Ausgabe ist also:
line1 with a pattern
line3
line4 with a pattern
line6
line7 with a pattern
...
awk
ist so allgemein, dass Sie es verwenden können, um Ihre Aufgabe zu lösen, aber Sie müssten ein Skript schreiben. In diesem Fall wäre die Antwort also ja . Wie Sie bereits herausgefunden haben,grep
können Sie Ihre Aufgabe bis zu einem gewissen Grad erledigen, aber vielleicht nicht alles. Warum konzentrieren Sie sich auf diese beiden Tools, erwähnen sie abersed
in Ihren Tags? Ist Ihre eigentliche Frage: Kann ich dies nur mit Standard-GNU-Tools ohne Skripterstellung tun / kombinieren? Die Antwort lautet wahrscheinlich auch Ja, kann aber aufgrund von Sonderfällen etwas kniffliger sein: Was ist beispielsweise die gewünschte Ausgabe, wenn das Muster in den ersten X- oder letzten X-Zeilen gefunden wird?Antworten:
grep
wird dies für Sie tun, mit Optionen-A
(nach) und-B
(vor) und-C
(Kontext). Ein Beispiel, das ich oft benutze, ist:da dieser Befehl nach dem Spiel 12 Zeilen anzeigt, einschließlich des Treibers, der zur Steuerung der Netzwerkkarte (-i net) verwendet wird. Im Allgemeinen lautet der Befehl:
Hiermit werden
m
Zeilen vor dem Spiel undn
Zeilen nach dem Spiel ausgegeben . Oder Sie können verwendenum insgesamt
n
Zeilen zu zeigen , die den gefundenen Text umgeben (halb vor, halb nach dem Spiel).quelle
Nachdem ich mich ein wenig mit dieser Frage befasst habe, denke ich, dass ich meinen Kommentar zur Machbarkeit mit Standard-GNU-Tools ohne Skripten überarbeiten muss. Dies kann aufgrund der Sonderfälle sehr schwierig sein.
Wenn es Ihnen nichts ausmacht, awk zu verwenden, könnte ich die folgende Lösung anbieten. Dieses Skript
context.awk
ist immer noch ziemlich prägnant:Es muss wie folgt aufgerufen werden:
wo
X
ist die gewünschte "Kontextentfernung" undPATTERN
das Suchmuster. Das Skript versucht, mehrere Musterkontexte in der Datei zu trennen, indem Zeilen---
dazwischen gedruckt werden . So zum Beispiel das Folgendesample.txt
mit diesem Aufruf
ergibt die folgende Ausgabe
quelle
awk
.Der folgende
sed
Befehl scheint für den von Ihnen beschriebenen Fall zu funktionieren, den ich neu formulieren würde: Drucken Sie die Zeile, die meinem Muster entspricht, drucken Sie nicht die unmittelbar folgende Zeile, drucken Sie auch die Zeile zwei Zeilen nach meinem Muster und suchen Sie dann weiter nach Musterübereinstimmungen.Es scheint ein bisschen hässlich zu sein, aber durch Hinzufügen zusätzlicher Befehle
n
(Zeile überspringen, zur nächsten wechseln) undH
(diese Zeile durch Anhängen an den Haltepuffer beibehalten) können Sie nach einer Musterübereinstimmung eine beliebige Keep / Skip-Beziehung erstellen.Beachten Sie, dass wir nach der Übereinstimmung zunächst die übereinstimmende Zeile mit dem
h
Befehl in den Haltepuffer kopieren . Schließlich tauschen wir den Halte- und Musterraum mit ausx
und drucken den Musterraum mitp
. An diesem Punktsed
wird die Datei zeilenweise weiter verarbeitet, um nach einer anderen Übereinstimmung zu suchen.Eine praktische Referenz für
sed
Befehle finden Sie hier .quelle
grep -A2 <pattern> file | grep -B1 <pattern> | grep -v "\-\-"
funktioniert bei mir:quelle