2010-03-04 13 views
8

Wie kann ich alle Zeilenenden in einer großen Datei (> 100 MB) ersetzen? Ich habe versucht,So ersetzen Sie Zeilenenden in VIM

:%s/\n/, /g

zu tun, aber es ist zu langsam.

+0

Warum möchten Sie dies in VIM tun. Sie werden nur mit einer langen Zeile enden, die Sie nicht lesen können (mit Augen, das ist.) Und welche Zeilenenden gibt es auch: DOS, UNIX, MAC oder eine Kombination? – Marichyasana

Antwort

8

Also, ich ging durch und getestet/timed einige der Antworten, die von anderen Menschen gegeben wurden, plus eine Python-Antwort von mir. Hier ist, was ich habe:

tr:

> time tr "\n" "," <lines> line 
real 0m1.617s 
user 0m0.100s 
sys  0m1.520s 

Python:

> time python -c 'import sys; print sys.stdin.read().replace("\n",", "),' <lines> line 
real 0m1.663s 
user 0m0.060s 
sys  0m1.610s 

awk:

> time awk '{printf("%s, ", $0)}' lines > line         
real 0m1.998s 
user 0m0.390s 
sys  0m1.600s 

Perl:

> time perl -e 'while (<>) { chomp; print "$_, " }' lines > line 
real 0m2.100s 
user 0m0.590s 
sys  0m1.510s 

sed:

> time sed 's/$/, /g' lines > line            
real 0m6.673s 
user 0m5.050s 
sys  0m1.630s 

Hier ist die Datei, die ich verwendet:

> ls -lh lines 
-rw-r--r-- 1 some one 101M 2010-03-04 19:54 lines 
> wc -l < lines 
1300000 
> head -n 3 < lines 
The pretty pink puma pounced on the unsuspecting aardvark, the scientist watched. 
The pretty pink puma pounced on the unsuspecting aardvark, the scientist watched. 
The pretty pink puma pounced on the unsuspecting aardvark, the scientist watched. 
> head -n 1 < lines | wc -c 
82 

Ursprünglich war die Timings in Cygwin genommen wurden, haben sie jetzt getroffen worden mit vollständig aktualisiert ubuntu 9.10. Außerdem wurde die Textdateigröße auf 100 MB mit 80 Zeichen breiten Zeilen erhöht. Wie Sie sehen können, ist alles andere als Sed eine gute Idee.

+2

ich bin sehr verdächtig auf Ihre awk Ergebnisse. Zeit, die Sie ein paar Mal befehlen, nicht nur einmal. Python sollte nicht schneller als awk sein, wenn man bedenkt, dass es Zeit braucht, um Module und Sachen zu importieren – ghostdog74

+0

Es wurde ein paar Mal gelaufen, das war durchschnittlich. Ich habe es nur etwa 10 mal, 1.7xx jedes Mal. Vielleicht wäre es anders, wenn ich nicht cygwin awk verwenden würde. –

+0

@ ghostdog74 Sie hatten Recht, meine awk Ergebnisse zu verdächtigen, ich lief es auf einer echten Linux-Box, und es war viel schneller. –

2

Verwenden Sie dieses Perl-Skript, um durch Ihre Datei zu gehen; es wäre schneller, als alles mit VIM im Speicher zu halten. Passen Sie die Ausgabe einfach an eine neue Datei an.

#!/usr/local/bin/perl 

while (<>) { 
    $_ =~ s/\n/,/g; 
    print $_; 
} 
+0

Ich vermute, der Perl-Interpreter ist nicht schlau genug, um zu wissen, dass '$ _' in diesem Fall keine neue Zeile haben kann, außer für das letzte Zeichen -' chomp' ist wahrscheinlich viel schneller. – Cascabel

+0

@Jefromi In meiner völlig unwissenschaftlichen Tests ist es etwa 300 ms schneller, chomp auf eine 100-Megabyte-Datei zu verwenden. –

0

Müssen Sie dies in vim tun?

Es gibt ein schönes Unix-Dienstprogramm, das zeichenbasierte Übersetzung durchführt. Es heißt tr. Einige reference.

In Ihrem Fall wäre es:

 
tr "\n" "," < input_file > output_file 
+0

Das ist fast sicher schneller als die Lösungen, die ich gepostet habe, aber leider ersetzt es "," anstelle von "," wie das OP gefordert hat. Ich bin mir nicht sicher, ob es einen Weg gibt, das mit "tr" zu machen, oder? – Cascabel

+0

tr nimmt nur ein Zeichen – ghostdog74

+0

Nein, es ist nicht, ich habe nicht bemerkt, den Platz dort. Um mehr als 1 Zeichen einzugeben, könnte man sed als jemanden verwenden, der unten veröffentlicht wurde. – pajton

3

:%s/$/, / von einem :1,$j gefolgt schneller sein könnte. Ansonsten tut es in einem externen Programm:

perl -e 'while (<>) { chomp; print "$_, " }' input_file > output_file 

awk '{printf("%s, ", $0)}' input_file > output_file 

Kennen Sie nicht die Spitze von meinem Kopf, die schnellsten sein würde.

+0

'perl -ne 'chomp; Drucken Sie "$ _", "Datei". '-n'" nimmt while-Schleife an " – ghostdog74

+0

Guter Anruf auf dem' -n'. – Cascabel

+0

@sparrkey, "Perl wird schneller ausgeführt" ist nicht gerechtfertigt. – ghostdog74

0
$ more file 
aaaa 
bbbb 
cccc 
dddd 
eeee 

$ awk 'NR>1{printf("%s, ", p)}{p=$0}END{print p}' file 
aaaa, bbbb, cccc, dddd, eeee 

$ sed -e :b -e '$!N;s/\n/, /;tb' file 
+0

Haben Sie Ihren sed Befehl getestet? sed 'N; s/\ n /, /' Datei – sparkkkey

+0

nicht wirklich. Es ist ein Schnitt eine Paste von Wiki, aber ich denke, Wiki kann manchmal nicht vertraut werden. – ghostdog74

0

Das beste Werkzeug ist sed und Sie können es verwenden mit:! Befehl

so verwendet :!sed -e 's/\n/,/g' % > %.tmp ; cat %.tmp > % ; rm %.tmp'

Sie benötigen eine tmp-Datei mit Änderung erstellen, bevor in der aktuellen Datei integrieren

+0

hast du deinen sed Befehl getestet? – ghostdog74

+0

ja ich teste es vor – shingara