2009-05-18 30 views

Antwort

12

Der Trick besteht darin, die letzte Zeile im "Laderaum" zu speichern.

sed -n ' 
/^xxxx/{n 
     n 
     x 
     d 
     } 
x 
1d 
p 
${x 
    p 
} 
' <input file> 

Beginnend mit den x - tauschen die aktuelle Eingabezeile mit dem Halteraum (x), dann für die erste Zeile gedruckt nichts (1d), drucken Sie die nachfolgenden Zeilen die Zeilen nur aus dem Laderaum getauscht(), tausche in der letzten Zeile den Haltebereich erneut und drucke was drin war ($x{x p}. Das lässt was tun, wenn wir die Ziellinie treffen (beginnend /^xxxx/) - lies die nächsten zwei Zeilen in den Musterraum (n n) und vertausche den Musterbereich mit dem Haltebereich (x) - dies lässt den Haltebereich mit der nächsten Zeile, die gedruckt werden soll, und den Musterbereich mit der Zeile vor dem Treffer, was h wollen wir nicht, so Graben wir es (d)

+0

Eine weitere Erklärung der 'x' Befehl, der den Musterbereich mit dem Haltepuffer "eXchanges": http://www.grymoire.com/Unix/Sed.html#uh-53 –

+0

Ich kann das obige Skript nicht ausführen. es sagt sed: FUNCTION/^ Muster/{n n x d} x 1d p $ {x p} kann nicht geparst werden nicht sicher warum? –

0

So würde ich es in Perl machen Vielleicht kann es helfen, Sie auf den richtigen Weg zu schicken ... Viel Glück!

open(INFILE,"<in.txt"); 
my(@arrayOutBoundData, $skipNextLine)l 
for (<INFILE>) { 
    if (not $skipNextLine) { 
     if (/^xxxx$/) { 
      pop(@arrayOutBoundData); 
      $skipNextLine = 1; 
     } else { 
      push(@arrayOutBoundData,$_); 
     } 
    } 
$skipNextLine = 0 
} 

open(OUTFILE,">out.txt"); 
for (@arrayOutBoundData) { 
    print OUTFILE; 
} 

(Nicht kein Perl auf diesem System bitte vergib jeder über Ort getestet.)

1

Sie this document überprüfen können. Es behandelt die Verwendung von sed, um mit mehreren Zeilen zu arbeiten.

-1
grep -v -f <(grep -1 "xxxx" file) file 
0

Dies könnte für Sie arbeiten (GNU sed):

echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' 
a 
b 

Dieses ein Fenster von zwei Zeilen in dem Musterraum hält und Wenn der erforderliche Regexp in der ersten oder zweiten Zeile gefunden wird, liest die folgende Zeile und löscht dann alle drei Zeilen. Die Randfälle sind, wenn der Regexp entweder in der ersten oder in der letzten Zeile gefunden wird, wenn keine Zeile vorher/nachher vorhanden ist. In diesen Fällen können nur zwei Zeilen gelöscht werden.

Übrigens hat diese Lösung möglicherweise einen Fehler in GNU sed entdeckt. Das M-Flag einer Adresse ermöglicht die Metazeichen ^ und $ als Null Länge Markierungen in einer Regexp für den Anfang und das Ende der Zeile in mehrzeiligen Zeichenfolgen verwendet werden. Die leere Adresse // verwendet eine zuvor angegebene Adresse. Sollte diese Adresse eine sein, die ein mehrzeiliges Flag enthält? Derzeit scheint es, die Flagge zu schließen, auch wenn es nicht das heißt

angegeben
sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file 

eine andere erzeugt (korrekt) führen zu:

sed 'N;/^xxxx/M{//d;$!N;d};P;D' file 

wenn xxxx auf der zweiten Zeile einer Datei erscheint.

+0

Fast, aber er will auch Zzzz verschwinden. –

+0

@SamuelEdwinWard einfache Lösung siehe bearbeiten. – potong

0

können Sie Folgendes verwenden:

sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}' 

Dies wird drei Linien mit einer Leerzeile ersetzen.

0

Sie können zuerst die umzukehren, verwenden sed die gefundene Zeile und die nächste Zeile (oder Zeilen, +Nd in sed Befehl), zu löschen und schließlich das Ergebnis umkehren zurück:

tac old.file | sed -e '/xxxx/,+1d' | tac > new.file 
Verwandte Themen