Wie entferne ich die zweite Zeile aufeinanderfolgender Zeilen, die mit demselben Wort beginnen?

8

Ich habe eine Textdatei mit vertauschten Zeilen, die mit 'TITLE' und 'DATA' beginnen, aber manchmal gibt es doppelte Zeilen, die mit 'TITLE' beginnen:

  

TITEL etwas   Daten einige Daten   TITEL etwas anderes   DATA einige andere Daten   TITEL noch etwas mehr   TITLE Zusatzinfo
  DATEN etwas mehr Daten

Ich möchte die doppelten Zeilen erkennen, die mit "TITLE" beginnen und nur die erste Zeile jedes Paares behalten.
Ich habe herausgefunden, dass der reguläre Ausdruck für das Erfassen dieser ^TITLE.*\n^TITLE.*\n ist, jetzt möchte ich dies in einen einzeiligen perl / bash / sed / awk Befehl integrieren, der die zweite Zeile entfernt und gib den Rest der Datei aus, aber ich konnte das nicht herausfinden.

    
Roey Angel 15.03.2013, 11:08
quelle

5 Antworten

3

Perl-Lösung:

%Vor%

Es merkt sich, ob die vorherige Zeile ein TITLE in der $t Variable war.

    
choroba 15.03.2013, 11:14
quelle
5

Hier ist eine Möglichkeit, wie Sie es mit GNU sed tun können:

%Vor%
  • N fügt eine zweite Zeile in den Musterbereich ein.
  • Die Übereinstimmung testet, wenn beide Zeilen mit TITLE beginnen.
  • Wenn ja, wird die zweite Zeile entfernt.
  • P; D druckt und löscht die erste Zeile im Musterbereich.

Ausgabe:

%Vor%

Edit - behandelt beliebig viele Wiederholungen

Wie von Nikina Reklawyks in den Kommentaren erwähnt, funktioniert die obige Lösung nur mit zwei aufeinanderfolgenden Zeilen beginnend mit TITLE , um beliebig viele Wiederholungen zu bewältigen, eine einfache Schleife kann wie folgt hinzugefügt werden:

%Vor%

Die ta -Anweisung bewirkt, dass sed zum :a -Label springt, wenn s/// erfolgreich ist.

Eine andere Möglichkeit wäre, den uniq -Befehl von coreutils zu verwenden, dies ist nicht so flexibel, funktioniert aber in diesem Fall trotzdem gut:

%Vor%     
Thor 15.03.2013 11:31
quelle
4

Eine Möglichkeit:

%Vor%     
Guru 15.03.2013 11:12
quelle
2

Es klingt für mich so, als hätten Sie Datensätze, die aus zwei Feldern bestehen, TITLE und DATA, und wenn Sie das zweite Feld verpassen, möchten Sie den Datensatz löschen. Aber das hast du in deiner Frage nicht gefragt. Also hier ist eine Möglichkeit zu tun, was Sie gefragt haben:

%Vor%

Die Idee hier ist, dass wir eine Variable auf einen TITEL setzen werden, wenn wir sie sehen und nicht schon eine betitelte Menge haben, dann drucken wir sie nur, wenn wir eine DATEN sehen. Dies funktioniert für die eingegebenen Daten, wenn ich Ihre Frage richtig gelesen habe. Ausgabe ist:

%Vor%

Wie Sie sehen, wurde die letzte TITLE-Zeile in Ihrem Dataset gelöscht.

Und hier ist ein anderer Weg, dies in awk zu tun ...

%Vor%

In diesem Fall überspringt der erste Ausdruck Titel, wenn t festgelegt wurde. Der zweite Ausdruck setzt t nicht richtig. Der dritte Ausdruck legt fest, ob für Titel und der letzte Ausdruck ( 1 ) die Zeile ausgibt. Natürlich werden die letzten drei Ausdrücke nicht ausgeführt, wenn wir die Zeile im ersten Ausdruck übersprungen haben. Es erzeugt die gleiche Ausgabe wie oben und schaut nicht auf /^DATA/ .

Schließlich ist dies der kleinste Code, aber die seltsamste Logik:

%Vor%

Er druckt alle Datenzeilen oder jede Zeile, in der t nicht gesetzt ist, und setzt t effektiv auf einen booleschen Wert, was sich auf die Auswertung der nächsten Zeile auswirkt. Wenn Sie dies in csh oder tcsh tun, achten Sie auf das Ausrufezeichen, das in diesen Shells möglicherweise maskiert werden muss.

    
ghoti 15.03.2013 11:36
quelle
1

Probieren Sie diesen One-Liner:

%Vor%

Ausgabe:

%Vor%     
Kent 15.03.2013 11:12
quelle

Tags und Links