Lavorare con file enormi in VIM


108

Ho provato ad aprire un file enorme (~ 2 GB) in VIM ma si è bloccato. In realtà non ho bisogno di modificare il file, basta saltare in modo efficiente.

Come posso lavorare con file molto grandi in VIM?



5
Vim dovrebbe essere a posto finché tu :set binaryprima ...
effimero

1
Questo è un buon obiettivo per un nuovo filesystem fuse! splitfs o qualcosa del genere ... ci sto!
rodrigo

1
Troppo tardi ... questo esiste già: sourceforge.net/projects/joinsplitfs
rodrigo

5
Hai bisogno di un cercapersone, non di un editore signore! Vedi la risposta di Jim di seguito.
Lester Cheung

Risposte:


85

Oggi avevo un file da 12 GB da modificare. Il plugin vim LargeFile non ha funzionato per me. Ha ancora esaurito tutta la mia memoria e poi ha stampato un messaggio di errore :-(. Non ho potuto usare hexedit per nessuno dei due, poiché non può inserire nulla, basta sovrascriverlo. Ecco un approccio alternativo:

Suddividi il file, modifichi le parti e poi lo ricombini. Tuttavia, hai ancora bisogno del doppio dello spazio su disco.

  • Grep per qualcosa che circonda la riga che desideri modificare:

    grep -n 'something' HUGEFILE | head -n 1
    
  • Estrai quell'intervallo del file. Supponi che le righe che desideri modificare siano alla riga 4 e 5. Quindi:

    sed -n -e '4,5p' -e '5q' HUGEFILE > SMALLPART
    
    • L' -nopzione è richiesta per sopprimere il comportamento predefinito di sed per stampare tutto
    • 4,5p stampa le righe 4 e 5
    • 5q interrompe sed dopo l'elaborazione della riga 5
  • Modifica SMALLPARTutilizzando il tuo editor preferito.

  • Combina il file:

    (head -n 3 HUGEFILE; cat SMALLPART; sed -e '1,5d' HUGEFILE) > HUGEFILE.new 
    
    • cioè: scegli tutte le righe prima delle righe modificate da HUGEFILE (che in questo caso sono le prime 3 righe), combinalo con le righe modificate (in questo caso le righe 4 e 5) e usa questo insieme combinato di righe per sostituire equivalente (in questo caso le prime 5 righe) in HUGEFILE e scriverlo tutto in un nuovo file.

    HUGEFILE.newsarà ora il tuo file modificato, puoi eliminare l'originale HUGEFILE.


30

Questa è una domanda ricorrente da molti anni. (I numeri continuano a cambiare, ma il concetto è lo stesso: come faccio a visualizzare o modificare i file che sono più grandi della memoria?)

Ovviamente moreo lesssono buoni approcci alla semplice lettura dei file --- lessoffre anche vicombinazioni di tasti per lo scorrimento e la ricerca.

Una ricerca Freshmeat su "file di grandi dimensioni" suggerisce che due editor sarebbero particolarmente adatti alle tue esigenze.

Uno potrebbe essere: lfhex ... un editor esadecimale di file di grandi dimensioni (che dipende da Qt). Quello, ovviamente, comporta l'utilizzo di una GUI.

Un altro sembrerebbe adatto all'uso su console: hed ... e afferma di avere un'interfaccia vimsimile a quella (inclusa una exmodalità?).

Sono sicuro di aver visto altri editor per Linux / UNIX che erano in grado di sfogliare i file senza caricare la loro interezza in memoria. Tuttavia, non ricordo nessuno dei loro nomi. Rendo questa risposta una voce "wiki" per incoraggiare altri ad aggiungere i loro collegamenti a tali editor. (Sì, ho familiarità con i modi per aggirare il problema utilizzando splite cat; ma sto pensando agli editor, in particolare agli editor di console / curses che possono farne a meno e farci risparmiare tempo / latenze e sovraccarico di spazio su disco che tali approcci comportano) .


23

Dal momento che non è necessario modificare effettivamente il file:

  1. view(o vim -R) dovrebbe funzionare abbastanza bene su file di grandi dimensioni.
  2. Oppure puoi usare moreoless

Con "strozzatori" intendi che ci vuole un po 'per aprirsi? O si blocca davvero? Ci vogliono un po 'più di 4 minuti sulla mia macchina Linux non così recente per aprire un file da 2,7 GB view(appena provato e programmato). Certo, non è esattamente istantaneo, ma funziona.
ChssPly76

Sì, si blocca. Sono sicuro che se avessi aspettato si sarebbe aperto alla fine. Sono andato con meno perché si apre subito e sono abituato alla navigazione.
hoju

9

Ho scritto un piccolo script basato sulla risposta di Florian che usa nano (il mio editor preferito):

#!/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

Usalo in questo modo:

sh hfnano yourHugeFile 3 8

In questo esempio, nano aprirà le righe da 3 a 8, puoi modificarle e quando salvi e esci, quelle righe nell'enorme file verranno automaticamente sovrascritte con le righe salvate.


3

Ho avuto lo stesso problema, ma era un dump mysql da 300 GB e volevo sbarazzarmi di DROPe passare CREATE TABLEa CREATE TABLE IF NOT EXISTSquindi non volevo eseguire due invocazioni di sed. Ho scritto questo rapido script Ruby per ingannare il file con queste modifiche:

#!/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
}

Invocato come

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

Solo per notare per l'esecuzione, per eseguirlo come un exe richiede chmod +x mreplace.rbprima, potresti anche semplicementeruby mreplace.rb ..
Smar

Grazie @Steeve McCauley! Bel lavoro. Esattamente quello che stavo cercando quando cercavo la risposta a questa domanda.
Nate Ritter


2

È già tardi, ma se vuoi semplicemente navigare nel file senza modificarlo, catpuoi fare anche il lavoro.

% cat filename | less

o in alternativa semplice:

% less filename

8
Notare che catinserire prima il file è follemente stupido, poiché significa che il file sarebbe completamente in memoria (quindi è lesspossibile cercare il file) o non può essere cercato affatto; catfornisce solo un flusso di output statico.
Smar

1

emacs funziona molto bene con file fino a centinaia di megabyte, l'ho usato sui file di registro senza troppi problemi.

Ma generalmente quando ho un qualche tipo di compito di analisi, trovo che scrivere uno script perl sia una scelta migliore.


0

Vecchio filo. Ma comunque (gioco di parole :)).

 $less filename

less funziona in modo efficiente se non si desidera modificare e basta guardarsi intorno quale è il caso per esaminare file di registro di grandi dimensioni.

Cerca in meno opere come vi

La parte migliore, è disponibile per impostazione predefinita sulla maggior parte delle distribuzioni. Quindi non sarà un problema anche per l'ambiente di produzione.


La ricerca in un file di testo da 650 MB con meno si è rivelata una PITA. Usare vim con LargeFile funziona come un fascino.
MariusCC

2
@MariusCC Allora non hai lavorato con più di 2 GB di file, il tuo fascino svanirà con il crash!
immersione profonda

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.