So drucken Sie eine Zeile, wenn diese oder die nächste Zeile keine bestimmte Zeichenfolge enthält

8

Input.txt:

    8B0C
    remove
    8B0D
    remove
    8B0E
    remove
    8B0F
    8B10
    remove
    8B14
    remove
    8B15
    remove
    8B16
    remove
    8B17
    remove
    8AC0
    8AC1
    remove
    8AC2
    remove
    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

Gewünschte Ausgabe:

    8B0F
    8AC0
    8AE4
    8AE5

Ich möchte eine Zeile drucken, wenn diese oder die nächste Zeile nicht "Entfernen" enthält. Ich benutze Solaris 5.10, KSH.

ayrton_senna
quelle
@don_crissti Danke, ich kann diese Frage als beantwortet markieren, wenn Sie Ihre Antwort posten, anstatt sie zu kommentieren.
ayrton_senna

Antworten:

14

Mit sed:

sed '$!N;/remove/!P;D' infile

Dadurch wird die Next-Linie in den Musterraum gezogen (falls nicht !in der $letzten Zeile) und geprüft, ob der Musterraum übereinstimmt remove. Wenn dies nicht der Fall ist (dh , keine der beiden Zeilen im Musterbereich enthält die Zeichenfolge remove), Pwird bis zum ersten \nEwline-Zeichen gedruckt (dh es wird die erste Zeile gedruckt). Dann wird Dbis zum ersten \nEwline-Zeichen geöffnet und der Zyklus neu gestartet. Auf diese Weise befinden sich nie mehr als zwei Linien im Musterraum.


Es ist wahrscheinlich einfacher zu verstehen , die N, P, DZyklus , wenn Sie hinzufügen , lvor und nach der Nim Musterraum aussehen:

sed 'l;$!N;l;/remove/!P;D' infile

Verwenden Sie also nur die letzten sechs Zeilen aus Ihrem Beispiel:

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

Der letzte Befehl gibt Folgendes aus:

    8AC3 $
    8AC3 \ n $ entfernen
    entferne $
    entferne \ n 8AE4 $
    8AE4 $
    8AE4 \ n 8AE5 $
    8AE4
    8AE5 $
    8AE5 \ n 8AE6 $
    8AE5
    8AE6 $
    8AE6 \ n $ entfernen
    entferne $
    entferne $

Hier ist eine kurze Erklärung:

cmd Ausgabe cmd
l     8AC3$                  N # read in the next line
l     8AC3\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                N # read in the next line
l     remove\n    8AE4$      D # delete up to \n (pattern space matches so no P)
l     8AE4$                  N # read in the next line
l     8AE4\n    8AE5$        # pattern space doesn't match so print up to \n
P     8AE4                   D # delete up to \n
l     8AE5$                  N # read in the next line
l     8AE5\n    8AE6$        # pattern space doesn't match so print up to \n
P     8AE5                   D # delete up to \n 
l     8AE6$                  N # read in the next line
l     8AE6\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                # last line so no N 
l     remove$                D # delete (pattern space matches so no P)
don_crissti
quelle
5
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 
Glenn Jackman
quelle
2
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

Die obige Methode liest Datensätze nicht zeilenweise , sondern liest mehrzeilige Datensätze von einem Datensatztrenner (RS) zum nächsten (oder Dateiende) - RSwobei dies die "Entfernen" -Zeile selbst (einschließlich ihrer) ist nachstehend `\ n).

Der !RTTest wird benötigt, wenn die letzte Zeile keine RSZeile ist.
RT, ein Gawk-Ismus , ist der eigentliche Text des aktuellen Datensatzes RS.
gensubist auch ein Gawk-Ismus .

Wenn Sie eine Markierungslinie überprüfen müssen , dass Streichhölzer „Entfernen“ überall in der Linie, gegenüber einer Linie , die gleich auf „Entfernen“, dann ändern Sie einfach den Record - Separator zu:

`RS="[^\n]*remove[^\n]*\n"`  

Ausgabe:

8B0F
8AC0
8AE4
8AE5
Peter.O
quelle