2010-03-04 4 views
8

Как заменить все строки в большом файле (> 100 МБ)? Я попытался сделатьКак заменить строки в VIM

:%s/\n/, /g

, но это слишком медленно.

+0

Почему вы хотите сделать это в VIM. Вы просто закончите с одной длинной строкой, которую вы не можете прочитать (с глазами, которые есть). Кроме того, существуют ли какие-то окончания строк: DOS, UNIX, MAC или комбинация? – Marichyasana

ответ

8

Итак, я прошел и испытанный/приуроченные некоторые из ответов, которые были даны другими людьми, плюс собственный ответ python. Вот что я получил:

тр:

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

питон:

> 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 

СЭД:

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

Вот файл я использовал:

> 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 

Первоначально тайминги были приняты в Cygwin, они теперь были взяты с полностью обновлено ubuntu 9.10. Кроме того, размер текстовых файлов был увеличен до 100 мегабайт, а строки - 80 символов. Как вы можете видеть почти все, кроме седа, это хорошая идея.

+2

Я очень подозрительно отношусь к вашим результатам awk. время вы командуете несколько раз, а не один раз. Python не должен быть быстрее awk, учитывая, что требуется время для импорта модулей и прочее. – ghostdog74

+0

Он прошел несколько раз, что было примерно в среднем. Просто запустил его еще 10 раз, 1,7хх каждый раз. Возможно, было бы иначе, если бы я не использовал cygwin awk. –

+0

@ ghostdog74 Вы были правы, чтобы заподозрить мои результаты awk, я повторно запустил его в реальной коробке linux, и это было намного быстрее. –

2

Используйте этот Perl-скрипт для просмотра вашего файла; это будет быстрее, чем держать все в памяти с помощью VIM. Просто отправьте вывод на новый файл.

#!/usr/local/bin/perl 

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

Я предполагаю, что интерпретатор perl недостаточно умен, чтобы знать, что в этом случае '$ _' не может иметь новую строку, за исключением последнего символа -' chomp', вероятно, намного быстрее. – Cascabel

+0

@Jefromi В моем совершенно ненаучном тестировании, это примерно на 300 мс быстрее, чтобы использовать chomp в файле размером 100 мегабайт. –

0

Вам нужно сделать это в vim?

Существует хорошая утилита Unix, которая выполняет перевод на основе символов. Он называется tr. reference.

В вашем случае это будет:

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

Это почти наверняка быстрее, чем решения, которые я опубликовал, но, к сожалению, он заменяет «,» вместо «,» по запросу ОП. Я не уверен, что есть способ сделать это с помощью 'tr', не так ли? – Cascabel

+0

tr принимает только один символ – ghostdog74

+0

Нет, я не заметил места там. Чтобы ввести более 1 символа, можно использовать sed как кто-то, размещенный ниже. – pajton

3

:%s/$/, / с последующим :1,$j может быть быстрее. В противном случае, это сделать во внешней утилиты:

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

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

Не знаю с верхней части моей головы, которая будет самым быстрым.

+0

'perl -ne 'chomp; напечатайте «$ _», «файл». '-n'" принимает while loop " – ghostdog74

+0

Хороший вызов на' -n'. – Cascabel

+0

@sparrkey, «perl будет работать быстрее» не оправдано. – 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

Вы проверили команду sed? sed 'N; s/\ n /, /' файл – sparkkkey

+0

не очень. его вырезать пасту wiki, но я думаю, что вики иногда нельзя доверять. – ghostdog74

0

Лучший инструмент sed, и вы можете использовать его с:! Команда

поэтому используйте :!sed -e 's/\n/,/g' % > %.tmp ; cat %.tmp > % ; rm %.tmp'

Вам нужно создать TMP файл с изменениями, прежде чем включить в текущем файле

+0

Вы проверили команду sed? – ghostdog74

+0

да Я тестирую его до – shingara

Смежные вопросы