【问题标题】:How to replace line-endings in VIM如何在 VIM 中替换行尾
【发布时间】:2010-03-04 14:37:13
【问题描述】:

如何替换大文件 (>100MB) 中的所有行尾? 我已经尝试过

:%s/\n/, /g

但是太慢了。

【问题讨论】:

  • 为什么要在 VIM 中这样做。你最终会得到一个你看不懂的长行(用眼睛)。另外,存在哪些行尾:DOS、UNIX、MAC 或组合?

标签: vim replace line-endings


【解决方案1】:

所以,我检查并测试/计时了其他人给出的一些答案,以及我自己的 python 答案。这是我得到的:

tr:

> 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

sed:

> 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 个字符宽。正如您所看到的,除了 sed 之外的其他任何东西都是一个好主意。

【讨论】:

  • 我非常怀疑您的 awk 结果。你命令几次,而不仅仅是一次。考虑到导入模块和东西需要时间,Python 不应该比 awk 快
  • 它运行了几次,这大约是平均水平。只运行了大约 10 次,每次 1.7xx。如果我不使用 cygwin awk 可能会有所不同。
  • @ghostdog74 你怀疑我的 awk 结果是对的,我在一个真正的 linux 机器上重新运行它,而且速度要快得多。
【解决方案2】:

:%s/$/, / 后跟 :1,$j 可能会更快。否则,请在外部实用程序中执行:

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

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

我不知道哪个会最快。

【讨论】:

  • perl -ne 'chomp; print "$_, "' file-n“假设while循环”
  • @sparrkey,“perl 会运行得更快”是不合理的。
  • @ghostdog74 你是对的,它不是。事实上,它是相当可比的。和 python 和 tr 一样。
【解决方案3】:

使用这个 Perl 脚本来检查你的文件;它比使用 VIM 将所有内容保存在内存中要快。只需将输出通过管道传输到一个新文件。

#!/usr/local/bin/perl

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

【讨论】:

  • 我猜 perl 解释器不够聪明,无法知道在这种情况下 $_ 除了最后一个字符外不能有换行符 - chomp 可能快得多。跨度>
  • @Jefromi 在我完全不科学的测试中,在 100 兆文件上使用 chomp 大约快 300 毫秒。
【解决方案4】:

你必须在 vim 中这样做吗?

有一个不错的 Unix 实用程序可以进行基于字符的翻译。它被称为tr。 一些reference

在你的情况下是:

tr "\n" "," &lt 输入文件 &gt 输出文件

【讨论】:

  • 这几乎肯定比我发布的解决方案要快,但不幸的是,它按照 OP 的要求替换了“,”而不是“,”。我不确定tr 有没有办法做到这一点,有吗?
  • tr 只取单个字符
  • 不,没有,我没有注意到那里的空间。要输入超过 1 个字符,可以使用下面发布的 sed。
  • 是的,但 sed 确实不是一个好选择 - 它正在执行相同的正则表达式替换,这在 Vim 中太慢了。
  • 我知道这个命令,但我试图找到仅 vim 的解决方案,而不使用任何外部工具。
【解决方案5】:

最好的工具是 sed,您可以将它与 :!命令

所以使用:!sed -e 's/\n/,/g' % &gt; %.tmp ; cat %.tmp &gt; % ; rm %.tmp'

在集成到当前文件之前,您需要创建一个带有更改的 tmp 文件

【讨论】:

    【解决方案6】:
    $ 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
    

    【讨论】:

    • 并非如此。它是 wiki 的粘贴,但我想 wiki 有时是不可信的。
    猜你喜欢
    • 1970-01-01
    • 2017-06-22
    • 2010-09-10
    • 2010-09-09
    • 2010-09-11
    相关资源
    最近更新 更多