2016-06-26 9 views
2

Leute, Ich habe awk Befehl verwendet, um die Duplikate mit awk.Das Problem ist, dass ich wegen CRLF am Ende jeder Zeile ist. Gibt es einen Weg in Awk, dass ich CRLF vom Vergleich verwerfen kann?entfernen Duplikate Dateien mit CRLF mit dem Befehl awk

Command I verwendet: awk '!seen[$0]++'

Bilanz

HelloworldCRLF 
how are youCRLF 
Helloworld 

Die erste und dritte Platte sind gleich und ich erwartete sie entfernt werden. Ich denke, da die letzte Zeile keine CRLF hat, bleibt sie in der Ausgabe. Ich habe versucht, CRLF am Ende des Datensatzes hinzuzufügen, um sicherzustellen, dass der Befehl awk es entfernt, und es tut, aber manchmal hat der letzte Datensatz eine CRLF und ich am Ende mit einer zusätzlichen Leerzeile (Becuase I CRLF hinzufügen). Gibt es eine Möglichkeit, eine solche Situation zu beheben?

Übrigens wurde die Datei in Windows generiert.

+0

@WalterA, die '\ r' aus der ganzen Datei entfernen würde, nicht nur das Ende jeder Zeile, und in jedem Fall extra '\ r's ist nicht das OPs Problem, sein Problem ist eine fehlende Zeilenumbruch (CRLF in seinem Fall) am Ende der Datei. –

Antwort

2

Sie konnten die CRLF-Sequenz auf den Datensatz Trennzeichen hinzufügen:

awk -v RS='\n|\r\n' '!seen[$0]++' file 
+1

Nur in GNU awk oder einem anderen Nicht-POSIX-awk, das eine RS mit mehreren Zeichen erlaubt. Sie können es prägnanter schreiben als 'RS = '\ r? \ N'' btw. Dies ist nicht das OP-Problem, sein Problem ist jedoch ein fehlender Zeilenumbruch (CRLF in seinem Fall) am Ende der Datei. –

3

Ersetzen Sie jede Instanz von \r vor dem Vergleich zu tun.

awk '{gsub(/\r/,"")}; !seen[$0]++' 
+0

Das wird jede 'Mittellinie' entfernen. Du solltest wirklich '/ \ r $ /' verwenden. Dies ist nicht das OP-Problem, sein Problem ist jedoch ein fehlender Zeilenumbruch (CRLF in seinem Fall) am Ende der Datei. –

2

Ihr Problem ist nicht, dass Windows CRs hinzugefügt vor jedem LF (wie alle anderen so weit zu denken schien), ist es, dass die Datei eine neue Zeile fehlt (was Windows ist die CRLF-Kombination) am Ende der Datei. Alle Wetten sind deaktiviert, wenn ein UNIX-Befehl für eine Datei ausgeführt wird, die keinen abschließenden Zeilenumbruch hat, da sie zu diesem Zeitpunkt keine echte "Textdatei" mehr ist. Können Sie ändern, welches Werkzeug die Datei erzeugt, um eine abschließende neue Zeile zu erzeugen? Wenn nicht, dann tun Sie

printf '\r\n' >> file 

bevor Sie awk oder ein anderes Werkzeug darauf ausführen. DANN können Sie dos2unix oder irgendeinen anderen Vorschlag laufen lassen, um \r s zu behandeln/zu entfernen, wenn notwendig. Zum Beispiel:

$ cat -v file 
Helloworld^M 
how are you^M 
Helloworld$ 

Beachten Sie die $ die nach dem letzten Helloworld meine Aufforderung sofort ist aufgrund der fehlenden Newline in der Datei. Jetzt:

$ awk -v BINMODE=3 '!seen[$0]++' file | cat -v 
Helloworld^M 
how are you^M 
Helloworld 
$ 
$ printf '\r\n' >> file 
$ 
$ awk -v BINMODE=3 '!seen[$0]++' file | cat -v 
Helloworld^M 
how are you^M 
$ 
$ dos2unix file 
dos2unix: converting file file to Unix format... 
$ 
$ awk '!seen[$0]++' file | cat -v 
Helloworld 
how are you 
$ 

Ich habe -v BINDMODE=3 mit gawk zu verwenden, auf Cygwin über die untere Ebene Primitiven, um zu verhindern Strippen den \r s vor der gaffen Skript sie sieht.

WRT die Frage in den Kommentaren, hier ist, warum Sie nicht nur auf jede Datei ausführen dos2unix, die auf Ihrem dodorstep auftaucht. Stellen Sie sich diese Datei, die Zeilenumbrüche (control-Ms) als Feldtrennzeichen verwendet:

$ printf 'a\rb\r\nd\r\rf\n' > file 

$ cat -v file 
a^Mb^M 
d^M^Mf 

$ awk -v BINMODE=3 -F'\r' '{for (i=1;i<=NF;i++) print NF, i, "<"$i">"; print "----"}' file 
3 1 <a> 
3 2 <b> 
3 3 <> 
---- 
3 1 <d> 
3 2 <> 
3 3 <f> 
---- 

Wie Sie sehen awk erkennt korrekt, dass jede Zeile 3 Felder hat und das Feld 3 leer auf der Linie 1, während Feld 2 leer in Zeile 2.Lassen Sie uns jetzt dos2unix darauf laufen und versuchen Sie es erneut:

$ dos2unix file 
dos2unix: converting file file to Unix format... 

$ cat -v file 
a^Mb 
d^M^Mf 

$ awk -v BINMODE=3 -F'\r' '{for (i=1;i<=NF;i++) print NF, i, "<"$i">"; print "----"}' file 
2 1 <a> 
2 2 <b> 
---- 
3 1 <d> 
3 2 <> 
3 3 <f> 
---- 

Wie Sie dos2unix die Datei 3 durch Strippen das leere Feld aus der Leitung beschädigt sehen 1, weil, wenn es \r\n sah angenommen, dass eine dos Linie Ende war, kein FS gefolgt von einem RS.

+0

Die Datei kann am Ende eine neue Zeile haben, oder sie kann fehlen. Ich sehe, dass es das Problem lösen würde, tat ich das, aber wenn die Datei bereits als neue Zeile dann der nächste Prozess, der dies liest, behandelt es als ein leerer Datensatz. Ist es eine gute Praxis, dos2unix für alle Dateien zu verwenden, sobald sie in Unix landen? – Garfield

+0

Nein, da nicht jede Datei Wagenrücklauf-dann-Zeilenvorschub als Datensatztrennzeichen verwendet, es könnte nur ein Teil der Daten in der Datei sein. Es hängt alles davon ab, was der Wagen zurückgibt ('\ r') ** mean **, wenn sie vor einem Zeilenvorschub (' \ n') in Ihrer Anwendung stehen. Ich habe meiner Antwort ein Beispiel hinzugefügt, um einen Grund zu zeigen, warum man 'dos2unix' nicht einfach blind für jede Datei ausführen kann. Außerdem löst dos2unix Ihr fehlendes Newline-Problem nicht - es löscht nur '\ r' vor' \ n's, es fügt keine fehlenden Zeilenumbrüche am Ende der Dateien hinzu. Google für den Umgang damit. –

+0

Warten Sie - warum haben Sie http://StackOverflow.com/a/38036695/1745001 als Ihre akzeptierte Antwort ausgewählt? Das Problem, dass die Antwort zu lösen versucht (DOS Zeilen Endungen) hat absolut nichts mit Ihrem Problem zu tun (fehlende Zeilenumbrüche am Ende der Datei) und wäre nicht die richtige Lösung, wenn das Ihr Problem wäre. –

Verwandte Themen