在 VIM 中处理巨大的文件

我试着在 VIM 中打开一个大约2GB 的文件,但是打不开。我实际上不需要编辑文件,只需要有效地跳转。

How can I go about working with very large files in VIM?

133860 次浏览

Emacs 可以很好地处理100兆字节的文件,我在处理日志文件时没有遇到太多麻烦。

但是通常当我有某种分析任务时,我发现编写 perl 脚本是一个更好的选择。

因为实际上你不需要编辑文件:

  1. view (or vim -R) should work reasonably well on large files.
  2. 或者你可以使用 more或者 less

这是多年来反复出现的问题。(数字不断变化,但概念是相同的: 如何查看或编辑大于内存的文件?)

显然,moreless是仅仅读取文件的好方法——-less甚至提供了 vi这样的键绑定,用于滚动和搜索。

对“大文件”的 新人搜索表明,两个编辑器将特别适合您的需要。

一个是: Lfhex... 一个大型文件十六进制编辑器(取决于 Qt)。显然,这需要使用 GUI。

另一个似乎适合于控制台使用: Hed... 它声称有一个类似于 vim的接口(包括 ex模式?).

我肯定见过其他 Linux/UNIX 编辑器能够在不将文件全部加载到内存中的情况下对文件进行分页。但是,我不记得他们的名字了。我将这个回复作为一个“ wiki”条目,以鼓励其他人添加到这些编辑器的链接。(是的,我很熟悉使用 splitcat解决这个问题的方法; 但是我想到的是编辑器,特别是控制台/诅咒编辑器,它可以省去这些,并节省我们的时间/延迟和磁盘空间开销,这些方法都需要)。

我今天要编辑12GB 的文件。Vim LargeFile 插件不适合我。它仍然使用了我所有的内存,然后打印了一个错误消息:。我不能使用 heedit,因为它不能插入任何东西,只能覆盖。这里有一个替代方法:

您分割文件,编辑部分,然后重新组合它。但是您仍然需要两倍的磁盘空间。

  • 准备编辑行周围的内容:

    grep -n 'something' HUGEFILE | head -n 1
    
  • Extract that range of the file. Say the lines you want to edit are at line 4 and 5. Then do:

    sed -n -e '4,5p' -e '5q' HUGEFILE > SMALLPART
    
    • 需要使用 -n选项来禁止 sed 打印所有内容的默认行为
    • 4,5p打印第4行和第5行
    • 在处理第5行之后,5q终止 sed
  • Edit SMALLPART using your favourite editor.

  • 合并文件:

    (head -n 3 HUGEFILE; cat SMALLPART; sed -e '1,5d' HUGEFILE) > HUGEFILE.new
    
    • I.e: 从 HUGEFILE 中选择所有被编辑行之前的行(在本例中是前3行) ,将其与被编辑行(在本例中是第4行和第5行)组合,并使用这组组合行替换 HUGEFILE 中的等价行(在本例中是前5行) ,然后将其全部写入一个新文件。

    HUGEFILE.new现在将是你编辑的文件,你可以删除原来的 HUGEFILE

这是旧的,但是, use nano, vim or gvim

现在已经很晚了,但是如果你只是想浏览文件而不编辑它,cat也可以做这项工作。

% cat filename | less

或者简单地说:

% less filename

我有同样的问题,但它是一个300GB 的 mysql 转储,我想摆脱的 DROP和改变 CREATE TABLECREATE TABLE IF NOT EXISTS,所以不想运行两个调用的 sed。我编写了这个快速的 Ruby 脚本,用这些修改来欺骗文件:

#!/usr/bin/env ruby


matchers={
%q/^CREATE TABLE `foo`/ => %q/CREATE TABLE IF NOT EXISTS `foo`/,
%q/^DROP TABLE IF EXISTS `foo`;.*$/ => "-- DROP TABLE IF EXISTS `foo`;"
}


matchers.each_pair { |m,r|
STDERR.puts "%s: %s" % [ m, r ]
}


STDIN.each { |line|
#STDERR.puts "line=#{line}"
line.chomp!
unless matchers.length == 0
matchers.each_pair { |m,r|
re=/#{m}/
next if line[re].nil?
line.sub!(re,r)
STDERR.puts "Matched: #{m} -> #{r}"
matchers.delete(m)
break
}
end
puts line
}

就像

./mreplace.rb < foo.sql > foo_two.sql

我根据 Florian 的回答写了一个小脚本,使用了 nano (我最喜欢的编辑器) :

#!/bin/sh


if [ "$#" -ne 3 ]; then
echo "Usage: $0 hugeFilePath startLine endLine" >&2
exit 1
fi


sed -n -e $2','$3'p' -e $3'q' $1 > hfnano_temporary_file
nano hfnano_temporary_file
(head -n `expr $2 - 1` $1; cat hfnano_temporary_file; sed -e '1,'$3'd' $1) > hfnano_temporary_file2
cat hfnano_temporary_file2 > $1
rm hfnano_temporary_file hfnano_temporary_file2

像这样使用它:

sh hfnano yourHugeFile 3 8

在这个例子中,nano 将打开第3行到第8行,您可以编辑它们,当您保存和退出时,巨大文件中的这些行将被您保存的行自动覆盖。

陈词滥调,不过(双关语:)。

 $less filename

如果您不想编辑,只是四处查看,那么可以使用 less 来高效地工作,这就是检查巨大日志文件的情况。

在像 vi 这样的较少的作品中搜索

Best part, it's available by default on most distros. So won't be problem for production environment as well.

对于大的一行程序(从 1打印字符到 99) :

cut -c 1-99 filename