2010-03-04 15 views
8

Jak wymienić wszystkie zakończenia linii w dużym pliku (> 100 MB)? Próbowałem zrobićJak zamienić zakończenia linii w VIM

:%s/\n/, /g

ale jest zbyt powolny.

+0

Dlaczego chcesz to zrobić w VIM. Po prostu skończysz z jedną długą linią, której nie możesz odczytać (z oczami, które są.) Jakie są również zakończenia linii: DOS, UNIX, MAC lub kombinacja? – Marichyasana

Odpowiedz

8

Więc ja przeszedłem i testowanego/w czasie niektóre z odpowiedzi, które zostały podane przez innych ludzi, plus własną odpowiedź python. Oto co mam:

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 

Oto plik użyłem:

> 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 

pierwotnie taktowania zostały podjęte w Cygwin, że zostały już podjęte całkowicie zaktualizowany ubuntu 9.10. Rozmiar plików tekstowych został zwiększony do 100 megabajtów, z liniami o szerokości 80 znaków. Jak widać, prawie wszystko inne niż sed to dobry pomysł.

+2

Jestem bardzo podejrzliwy wobec wyników awk. raz komendujesz kilka razy, nie tylko raz. Python nie powinien być szybszy niż awk, biorąc pod uwagę, że potrzeba czasu na zaimportowanie modułów i rzeczy. – ghostdog74

+0

Zostało to uruchomione kilka razy, czyli było średnio. Po prostu uruchomiłem go około 10 razy, 1.7xx za każdym razem. Może byłoby inaczej, gdybym nie używał awionika cygwin. –

+0

@ ghostdog74 Miałeś rację podejrzewając moje wyniki awk, ponownie przetestowałem je na prawdziwym linuksowym pudełku i było znacznie szybciej. –

2

Ten skrypt Perla służy do przeglądania pliku; byłoby szybsze niż przechowywanie wszystkiego w pamięci za pomocą VIM. Po prostu wyprowadź wyjście do nowego pliku.

#!/usr/local/bin/perl 

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

Domyślam się, że interpreter perl nie jest wystarczająco inteligentny, aby wiedzieć, że w tym przypadku '$ _' nie może mieć znaku nowej linii z wyjątkiem ostatniej postaci -' chomp' jest prawdopodobnie dużo szybszy. – Cascabel

+0

@Jefromi W moich całkowicie nienaukowych testach, około 300ms szybciej używa chomp na pliku 100 megapikseli. –

0

Czy musisz to zrobić w vim?

Jest miły narzędzie Unix że robi tłumaczenie oparte znaków. Nazwano go tr. Niektóre reference.

W twoim przypadku będzie to:

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

Jest to prawie na pewno szybsze niż rozwiązania, które napisałem, ale niestety zastępuje "," zamiast "," jak żądał OP. Nie jestem pewien, czy można to zrobić za pomocą 'tr', prawda? – Cascabel

+0

tr zajmuje tylko pojedynczy znak – ghostdog74

+0

Nie, nie ma, nie zauważyłem tam miejsca. Aby umieścić więcej niż 1 znak, można użyć sed jako kogoś umieszczonego poniżej. – pajton

3

:%s/$/, / następnie :1,$j może być szybciej. W przeciwnym razie wykonaj to w narzędziu zewnętrznym:

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

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

Nie wiem z góry mojej głowy, która byłaby najszybsza.

+0

'perl -ne 'chomp; drukuj "$ _", "plik". '-n'" zakłada pętlę " – ghostdog74

+0

Dobre wywołanie na' -n'. – Cascabel

+0

@sparrkey, "perl będzie działał szybciej" nie jest uzasadniony. – 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

Czy przetestowałeś polecenie sed? sed 'N; s/\ n /, /' plik – sparkkkey

+0

niezupełnie. jest to skrót wiki, ale czasami nie można zaufać wiki. – ghostdog74

0

Najlepsze narzędzie to sed i można go używać z:! Komenda

więc używać :!sed -e 's/\n/,/g' % > %.tmp ; cat %.tmp > % ; rm %.tmp'

Musisz utworzyć plik tmp ze zmianami przed zintegrować w bieżącym pliku

+0

czy przetestowałeś polecenie sed? – ghostdog74

+0

Tak, testuję to przed – shingara

Powiązane problemy