Ich habe den folgenden Code, der Zeilen mit dem Muster banana
und 2 Zeilen danach entfernt:
sed '/banana/I,+2 d' file
So weit, ist es gut! Ich brauche es, um 2 Zeilen vorher zu entfernen banana
, aber ich kann es nicht mit einem "Minuszeichen" oder was auch immer bekommen (ähnlich wie was grep -v -B2 banana file
tun soll, aber nicht):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Teresa und Junior
quelle
quelle
awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'
. Dies ist nicht effizient, daher ist dies nur ein Hinweis, keine Lösung.tac file | sed ... | tac
. : Psed '/banana/,+2d' file
du auch machen könnenawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' filein
Da dies ein Kommentar und keine Antwort ist (es gibt bereits andere Antworten), werde ich nicht zu sehr ins Detail gehen, aber der springende Punkt ist, dass Sie immer die haben vorherige zwei Datensätze in vorh [0] und zurück [1], die „frischeste“ je nachdem , welche Iteration aber immer inprev[idx]
, also wenn Sie drucken, die Sie in!idx
dannidx
bestellen. Unabhängig davon, wechseln Sie abidx
und fügen Sie den aktuellen Datensatz einprev[idx]
.Antworten:
Sed zieht sich nicht zurück: Sobald eine Zeile verarbeitet wurde, ist sie fertig. "Finde eine Linie und drucke die vorherigen N Linien" funktioniert also nicht so, wie es ist, im Gegensatz zu "Finde eine Linie und drucke die nächsten N Linien", auf die man leicht pfropfen kann.
Wenn die Datei nicht zu lang ist und Sie mit GNU-Erweiterungen einverstanden zu sein scheinen, können Sie sie verwenden
tac
, um die Zeilen der Datei umzukehren.Ein weiterer Anstellwinkel besteht darin, ein Schiebefenster in einem Werkzeug wie awk beizubehalten. Anpassen von Gibt es eine Alternative zu den grep-A-B-C-Schaltern (um einige Zeilen davor und danach zu drucken)? (Warnung: minimal getestet):
Verwendung:
/path/to/script -v pattern='banana' -v before=2
quelle
sed
Sie können auch Schiebefenster verwenden, aber das resultierende Skript ist in der Regel so unleserlich, dass es einfacher ist, es nur zu verwendenawk
.awk
Skript ist nicht ganz richtig; wie sie ist druckt leere Zeilen und verfehlt die letzten Zeilen. Dies scheint das Problem zu beheben, aber es ist möglicherweise nicht ideal oder richtig:if (NR-before in h) { print...; delete...; }
... und imEND
Abschnitt:for (i in h) print h[i]
... Außerdem gibt das awk-Skript die entsprechende Zeile aus, dietac/sec
Version jedoch nicht. Aber die Frage ist ein bisschen mehrdeutig. Das "ursprüngliche" awk-Skript, zu dem Sie einen Link bereitgestellt haben, funktioniert einwandfrei. Ich mag es. Ich bin mir nicht sicher, wie sich der obige "Mod" auf den Druck danach auswirkt Zeilen ...Mit ex oder vim -e ist das ganz einfach
Der Ausdruck lautet: Löschen Sie für jede Zeile, die Bananen im Bereich von der aktuellen Zeile -2 bis zur aktuellen Zeile enthält.
Was cool ist, ist, dass der Bereich auch Rückwärts- und Vorwärtssuchen enthalten kann. So werden beispielsweise alle Abschnitte der Datei gelöscht, beginnend mit einer Zeile mit Apfel und endend mit einer Zeile mit Orange und einer Zeile mit Banane:
quelle
Verwenden des "Schiebefensters" in
perl
:quelle
Sie können dies ziemlich einfach tun mit
sed
:Ich weiß nicht, warum jemand etwas anderes sagen würde, aber um eine Linie zu finden und vorherige Linien zu drucken, ist
sed
das integrierteP
Rint-Primitiv integriert, das nur bis zum ersten\n
ewline-Zeichen im Musterraum schreibt . Das komplementäreD
Elete-Primitiv entfernt das gleiche Segment des Musterraums, bevor das Skript mit den verbleibenden Elementen rekursiv wiederverwendet wird. Abgerundet wird dies durchN
ein\n
Grundelement zum Anhängen der ext-Eingabezeile an den Musterraum nach einem eingefügten ewline-Zeichen.So dass eine Zeile
sed
alles sein sollte, was Sie brauchen. Sie ersetzen nurmatch
mit was auch immer Ihre Regexp ist und Sie sind golden. Das sollte auch eine sehr schnelle Lösung sein.Beachten Sie auch, dass ein
match
unmittelbar davorstehender Wert korrektmatch
als Auslöser für das Stummschalten der Ausgabe für die vorherigen beiden Zeilen und für das Stummschalten des Drucks gilt:Damit es für eine beliebige Anzahl von Zeilen funktioniert , müssen Sie nur einen Vorsprung holen.
So:
... löscht die 5 Zeilen vor einer Übereinstimmung.
quelle
Verwenden von
man 1 ed
:quelle