Mit OPEN STEP 4.2 OS ... verwende ich derzeit den folgenden sed
Befehl:
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
Dieser Befehl findet eine Instanz in einer Datei mit der IP 141.299.99.1 und enthält auch 3 Zeilen davor, was alles in Ordnung ist, mit der Ausnahme, dass ich auch alle Instanzen der IP und die 3 Zeilen davor finden möchte und nicht nur der erste.
Antworten:
Hier ist ein Versuch
grep -B3
, anhand dieses GNU sed-Beispiels ein sed-Moving-Fenster zu emulieren (aber hoffentlich POSIX-konform - mit der Bestätigung an @ StéphaneChazelas):Die ersten beiden Ausdrücke bereiten einen mehrzeiligen Musterpuffer vor und ermöglichen es ihm, den Kantenfall zu behandeln, bei dem vor der ersten Übereinstimmung weniger als 3 Zeilen des vorhergehenden Kontexts vorhanden sind. Der mittlere Ausdruck (Regex-Übereinstimmung) druckt eine Linie vom oberen Rand des Fensters, bis der gewünschte Übereinstimmungstext durch den Musterpuffer gewellt ist. Das
$!N;D
Fenster wird um eine Zeile gescrollt, es sei denn, es erreicht das Ende der Eingabe.quelle
-e
ist nicht GNU-spezifisch. Um POSIX / portable zu sein, brauchen Sie es, da es nichts danach geben kann}
(und Sie brauchen ein;
davor).-e '1h;2,4{H;g;}' -e '1,3d'
? Ich habe kein Nicht-GNU-System zum Testen (und der GNU sed---posix
Schalter scheint es nicht zu interessieren).sed
der Erbstück-Toolchest testen, die vom traditionellen Unix-Sed abstammt. Die POSIX / Unix-Spezifikation fürsed
ist unter pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlgrep
wird dies besser machen:Die
-B 3
Möglichkeit , die drei Zeilen vor jedem Treffer auszudrucken. Dies wird--
zwischen jeder Gruppe von Zeilen gedruckt . Um dies zu deaktivieren, verwenden Sie--no-group-separator
ebenfalls.Die
-B
Option wird von GNUgrep
und den meisten BSD-Versionen ( OSX , FreeBSD , OpenBSD , NetBSD ) unterstützt, ist aber technisch keine Standardoption.quelle
Mit
sed
können Sie ein Schiebefenster machen.Das tut es. Aber Vorsicht - es ist
bash
ein verrücktes Verhalten, sich zu erweitern,!
selbst wenn es zitiert wird !!! Wenn Sie den Befehlsstring aus Ihrem Befehlsverlauf eingeben, wird er möglicherweise etwas verrückt. Stellen Sie dem Befehl Folgendes voranset +H;
wenn dies der Fall ist. Um es dann wieder zu aktivieren (aber warum ???), mache esset -H
danach.Das würde natürlich nur zutreffen, wenn Sie es benutzen
bash
- obwohl ich nicht glaube, dass Sie es sind. Ich bin mir ziemlich sicher, dass Sie damit arbeitencsh
- (das ist zufällig die Shell, deren verrücktes Verhaltenbash
mit der History-Erweiterung nachahmt, aber vielleicht nicht bis zu den Extremen, mit denen die c-Shell es aufgenommen hat) . So wohl einer\!
funktionieren. Ich hoffe.Es ist alles portabler Code: POSIX beschreibt seine drei Operatoren folgendermaßen: (obwohl es erwähnenswert ist, dass ich nur bestätigt habe, dass diese Beschreibung bereits 2001 existiert hat)
In der ersten Zeile fügen Sie dem Musterbereich eine zusätzliche Zeile hinzu. So sieht es aus:
Dann fügen Sie in der ersten Zeile und in jeder Zeile danach - mit Ausnahme der allerletzten - eine weitere hinzu Zeile zum Musterraum hinzu. So sieht es also aus:
Wenn Ihre IP-Adresse in Ihnen
P
vorkommt, geben Sie hier einfach Zeile 1 ein. Am Ende eines jeden ZyklusD
wird derselbe Vorgang ausgeführt, und Sie beginnen erneut mit dem, was noch übrig ist. Der nächste Zyklus sieht also so aus:...und so weiter. Wenn Ihre IP-Adresse auf einer dieser drei Adressen zu finden ist, wird jedes Mal die älteste ausgedruckt. Also bist du immer nur drei Zeilen vor sich.
Hier ist ein kurzes Beispiel. Für jede Zahl, die mit Null endet, wird ein dreizeiliger Puffer gedruckt:
Das ist ein bisschen komplizierter als in deinem Fall, weil ich mich von beiden abwechseln musste
0\n
Zeilenvorschub oder0$
Ende des Musterraums Ihrem Problem näher zu kommen - aber sie unterscheiden sich geringfügig darin, dass dies einen Anker erfordert - was seitdem etwas schwierig sein kann Der Musterraum verschiebt sich ständig.Ich habe die ungeraden Fälle 10 und 52 verwendet, um zu zeigen, dass, solange der Anker flexibel ist, auch die Ausgabe flexibel ist. Völlig portabel kann ich dieselben Ergebnisse erzielen, indem ich mich stattdessen auf den Algorithmus verlasse und Folgendes tue:
Und die Suche ausweiten, während ich mein Fenster einschränke - von 0 auf 9 und 0 und von 3 auf zwei Zeilen.
Wie auch immer, Sie haben die Idee.
quelle
sed '...' $filename
. Übrigens - ich habe die Punkte aus Ihrer eigenen Suchzeichenfolge weggelassen, aber das sind eigentlich keine Punkte in einem Muster - diese stehen für ein einzelnes Zeichen. Sie sollten wahrscheinlich tunoct\.oct\.oct\.oct
, um ihnen zu entkommen, damit sie nur mit Zeiträumen übereinstimmen.Da Sie erwähnen, dass Sie nicht die
-B
Option dazu habengrep
, können Sie mit Perl (zum Beispiel) ein Fenster mit 4 Zeilen verschieben:Rameshs Antwort ist ähnlich
awk
.quelle
Wenn verfügbar, können Sie pcregrep verwenden :
quelle
Sie können den gleichen grundlegenden Ansatz wie die anderen Nicht-Grep-Antworten in der Shell selbst implementieren (dies setzt eine relativ neue Shell voraus, die dies unterstützt
=~
):Alternativ können Sie die gesamte Datei in ein Array schlürfen:
quelle
Wenn Ihr System den
grep
Kontext nicht unterstützt , können Sie stattdessen ack-grep versuchen :ack
ist ein Tool wie grep, das für Programmierer optimiert wurde.quelle
perl
, können Sie verwendenack
.In dieser
awk
Lösung wird ein Array verwendet, das immer 3 Zeilen vor dem aktuellen Muster enthält. Wenn das Muster übereinstimmt, wird daher der Array-Inhalt zusammen mit dem aktuellen Muster gedruckt.Testen
Nachdem ich den Befehl ausgeführt habe, lautet die Ausgabe:
quelle
In den meisten Fällen
/141.299.99.1/
wird auch (zB)141a299q99+1
oder141029969951
weil passen.
in einem regulären Ausdruck ein beliebiges Zeichen dargestellt werden kann.Mit
/141[.]299[.]99[.]1/
ist sicherer, und Sie können am Anfang zusätzlichen Kontext hinzufügen und den gesamten regulären Ausdrucks paßt zu machen , am Ende sicher nicht3141.
,.12
,.104
etc.quelle