So entfernen Sie eine einzelne Zeile zwischen zwei Zeilen

So entfernen Sie eine einzelne Zeile zwischen zwei Zeilen

Ich habe Millionen von Datensätzen in einer Datei, die so aussehen

echo "NEW Cell"
grep "2553,24" out.2A25.20090308.64436.7.HDF.txt.text = 22.58   5.39  82.09 237
echo "NEW Cell"
grep "2555,20" out.2A25.20090308.64436.7.HDF.txt.text = 24.72   5.58  82.05 237
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120
echo "NEW Cell"
grep "2560,24" out.2A25.20090308.64436.7.HDF.txt.text = 19.38   5.54  82.30 170
echo "NEW Cell"

Jetzt möchte ich die Zeile mit „grep“ löschen, unter der Bedingung, dass es die EINZIGE Zeile zwischen den Zeilen ist, die „New Cell“ enthalten. Das heißt, wenn sich zwischen „New Cell“ eine Zeile mit „grep“ befindet, sollte diese Zeile gelöscht werden.

Wie macht man das?

Meine Ausgabe sollte so aussehen:

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

Antwort1

AWKLösung:

awk 'NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }
     /NEW Cell/{ f=1; n=NR+2; r=$0; next }
     f && n-NR==1 && /^grep /{ gr=$0; next }1' file
  • /NEW Cell/{ f=1; n=NR+2; r=$0; next }- auf der Begegnungslinie mitNEW Cell

    • f=1= Aktiv-Flag setzenf=1
    • n=NR+2n- als maximale Anzahl der zu verarbeitenden Folgezeilen festlegen (2 nächste Zeilen)
    • r=$0- die Linie erfassen
    • next- zum nächsten Datensatz springen
  • f && n-NR==1 && /^grep /- beim Auffinden der zweiten Zeile (gesichert durch ), die mit dem Schlüsselwort n-NR==1beginntgrep

    • gr=$0; next- grepZeile erfassen und zum nächsten (dritten) Datensatz springen
  • NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }- beim Erreichen der 3. entscheidenden Linie (gewährleistet durch NR==n)

    • if (/NEW Cell/) { f=0 }- wenn die 3. Zeile unter dem verarbeiteten Abschnitt Folgendes enthält NEW Cell: - aktuelle Verarbeitung zurücksetzen mit f=0(alle zuvor erfassten Zeilen werden übersprungen)
    • else print r ORS gr- andernfalls alle zuvor erfassten Zeilen drucken

Die Ausgabe:

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

Antwort2

Kompakte Lösung mit sed:

sed '/NEW Cell/!{H;d;};x;/\n.*\n/!d'

Wenn die Zeile nichts enthält, NEW Cellführen Sie die Ausführung aus H, um die Zeile an den Haltebereich anzuhängen und ddie Verarbeitung für diese Zeile zu stoppen.

Weitere Befehle werden also nur auf NEW CellZeilen angewendet: Das xvertauscht Musterraum und Halteraum, dadurch steht die Zeile nun im Halteraum und weitere Zeilen können angehängt werden, während der Musterraum alles aufnimmt, was an die letzte NEW CellZeile angehängt wurde. Deine Anforderung ist, dass zwischen den Zeilen mehr als eine Zeile steht NEW Cell, also müssen im Musterraum mindestens zwei Zeilenumbrüche stehen. Wenn nicht, lösche es ohne Ausgabe: /\n.*\n/!d.

Antwort3

Mit rudimentären awk...

Version 1 löscht nur grepZeilen, die der Beschreibung des OP folgen:

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
     else { f=1; s=$0 } } ! /^echo/ { print; f=0 } \
     ! /^echo/ && ! /^grep/ { print }' inputfile

Version 2 löscht einzelne grepZeilen sowie vorangehende Nicht-Grep-Zeilen, die der Beispielausgabe des OP folgen:

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
    else { f=1; s=s "\n" $0 } } /^echo/ { s=$0; f=0 } \
    ! /^echo/ && ! /^grep/ { print }' inputfile

Lesbare Form der Version 2...

/^grep/ { 
   if (found) {  # found==true : already encountered first grep line
       if (length(save) > 0) {
          print save
          save=""
       }
       print
   } else {
       found=1
       save=save "\n" $0  # append the first grep line to saved preceding line
   }
}

/^echo/ { 
    save=$0  # save this line for possible later printing
    found=0
}

# print anything else
! /^echo/ && ! /^grep/ { print }

Diese lange Form kann ausgeführt werden, indem der Inhalt in eine Datei (z. B. awkfile) eingefügt und ausgeführt wird awk -f awkfile inputfile.

Antwort4

gawk '
/\n.+\n/{
    printf("%s%s", RS, $0);
}' RS='echo "NEW Cell"\n' input.txt

Erläuterung:

  1. RS='echo "NEW Cell"\n'- RSist das Trennzeichen für den Eingabedatensatz, standardmäßig ein Zeilenumbruch. Jetzt wurde es in geändert echo "NEW Cell"\n, sodass alle Vorkommen dieser Zeichenfolge entfernt werden und alle Zeichen dazwischen zum Datensatzelement werden.
  2. /\n.+\n/{- nur für Datensätze, die diesem Muster entsprechen - Zeilenumbruch, ein oder mehrere Zeichen, Zeilenumbruch. Es stimmt also nur mit mehrzeiligen Datensätzen überein, der einzeilige Datensatz stimmt nicht überein, da er nur einen hat \n.
  3. printf("%s%s", RS, $0);- druckt den Datensatz, dem ein RS( echo "NEW Cell"\n) vorangestellt ist.

Ausgabe

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

verwandte Informationen