在VIM中处理大文件

116

我尝试在VIM中打开一个巨大的文件(大约2GB),但它卡住了。实际上,我并不需要编辑这个文件,只需要高效地跳转到其中的内容。

如何处理在VIM中处理非常大的文件?


1
这里有一个类似的问题:https://dev59.com/cnVC5IYBdhLWcg3w21Mq。 - GeoAvila
5
只要您首先执行 :set binary 命令,使用Vim应该就没有问题了。 - ephemient
1
这是一个新的熔断文件系统的好目标!叫 splitfs 或类似的东西... 我很感兴趣! - rodrigo
1
太晚了...这已经存在了:http://sourceforge.net/projects/joinsplitfs/ - rodrigo
5
您需要一台寻呼机,而不是编辑器先生!请查看下面Jim的回答。 - Lester Cheung
显示剩余3条评论
10个回答

93
今天我需要编辑一个12GB的文件。vim的LargeFile插件对我没有用,它仍然占用了我所有的内存,然后打印了一个错误信息 :-(。我也无法使用hexedit,因为它不能插入任何内容,只能覆盖。这里有一种替代方法:

你可以将文件分割成几部分进行编辑,然后重新合并。不过,你仍需要两倍的磁盘空间。

  • 使用grep查找要编辑行周围的某些内容:
  • grep -n 'something' HUGEFILE | head -n 1
    
  • 提取文件的范围。假设您想编辑的行在第4行和第5行。那么请执行以下操作:

  • sed -n -e '4,5p' -e '5q' HUGEFILE > SMALLPART
    
    • -n选项用于禁止sed的默认行为,即打印所有内容。
    • 4,5p打印第4和第5行。
    • 5q处理完第5行后终止sed。
  • 使用您喜欢的编辑器编辑SMALLPART

  • 合并文件:

  • (head -n 3 HUGEFILE; cat SMALLPART; sed -e '1,5d' HUGEFILE) > HUGEFILE.new 
    
    • 即从HUGEFILE中选择所有编辑前的行(在本例中为前3行),将其与编辑后的行(在本例中为第4和第5行)组合起来,并使用这组合好的行替换HUGEFILE中等效的行(在本例中为前5行),然后将所有内容写入一个新文件。

    HUGEFILE.new现在是您编辑后的文件,您可以删除原始的HUGEFILE文件。


31
这是多年来一直存在的问题。(数字可能有所变化,但概念相同:如何查看或编辑大于内存的文件?)
显然,仅仅读取文件可以使用moreless——less甚至提供了类似于vi的按键进行滚动和搜索。
Freshmeat上搜索“大文件”,建议使用两个适合你需求的编辑器。
一个是:lfhex...一个大文件十六进制编辑器(依赖于Qt)。显然,那需要使用GUI。
另一个似乎更适合控制台使用:hed...它声称有类似于vim的界面(包括一个ex模式?)。
我确信我曾经看过其他的Linux/UNIX编辑器能够浏览文件而不将它们全部加载到内存中。然而,我不记得它们的名字。我把这篇回答作为一个“wiki”条目,鼓励其他人添加自己知道的这样的编辑器的链接。(是的,我知道可以使用splitcat等工具绕过这个问题;但我考虑的是编辑器,特别是可以不需要这样做并节省我们时间/延迟以及磁盘空间开销的控制台/ curses编辑器)。

25

既然您不需要实际编辑文件:

  1. view(或 vim -R)可以很好地处理大文件。
  2. 或者您可以使用moreless

“Chokes”指的是需要一段时间才能打开吗?还是真的会崩溃?在我的不太新的Linux桌面上,用“view”打开2.7GB的文件需要大约4分钟左右(我刚试过并计时了)。当然,这并不是立即完成,但它确实可以工作。 - ChssPly76
是的,它会卡住。我相信如果我等待一段时间它最终会打开。我选择了更少的选项,因为它可以立即打开并且我已经习惯了这种导航方式。 - hoju

10

我根据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行,您可以编辑它们,当您保存并退出时,这些行在hugefile中将自动被您的保存行覆盖。


3

我曾遇到同样的问题,但是它是一个300GB的mysql转储文件,我想要去掉DROP并将 CREATE TABLE 更改为 CREATE 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

只需注意,要运行它作为exe文件,首先需要执行chmod +x mreplace.rb,您也可以直接执行ruby mreplace.rb .. - Smar
谢谢@Steeve McCauley!干得好。正是我在寻找这个问题的答案时所需要的。 - Nate Ritter

3

对于巨大的一行代码(从1打印字符到99):

cut -c 1-99 filename

1

虽然已经很晚了,但如果你只是想在不编辑文件的情况下浏览它,cat也可以完成任务。

% cat filename | less

或者简单地说:

% less filename

11
注意,首先运行 cat 命令是非常愚蠢的操作,因为它要么在内存中完全加载文件 (以便 less 可以查找文件),要么根本不能查找;cat 命令只提供静态输出流。 - Smar

1

Emacs在处理数百兆字节的文件时表现非常出色,我曾经用它来处理日志文件而没有遇到太多麻烦。

但通常情况下,当我需要进行某种分析任务时,我发现编写Perl脚本是更好的选择。


0

旧帖子。但尽管如此(双关语 :) )。

 $less filename

如果您只是浏览文件而不需要编辑的话,less 在检查大型日志文件时会非常高效。

在 less 中搜索的方式类似于 vi。

最好的部分是,在大多数发行版中它默认可用。因此,即使在生产环境中也不会有问题。


在650MB的文本文件中搜索使用less非常麻烦。 使用LargeFile插件的vim效果非常好。 - MariusCC
2
@MariusCC 那你就没处理过超过 2GB 的文件,否则它的魅力将随着崩溃而消失! - deepdive

-15

这个很老了,但是可以使用nano、vim或gvim。


5
这些工具无助于解决问题。 - Doug Wolfgram
1
Nano填满了内存然后崩溃了。 - Trynkiewicz Mariusz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接