Usando 'head' ou 'tail' no arquivo de texto HUGE - 19 GB

13

Eu tenho um problema com a exibição de blocos de um arquivo de texto muito grande. Este arquivo, aproximadamente 19 GB, é obviamente grande demais para ser visualizado por qualquer meio tradicional.

Eu tentei head 1 e tail 1 ( head -n 1 e tail -n 1 ) com os dois comandos reunidos de várias maneiras (para chegar a uma parte no meio) sem sorte. Minha máquina Linux com o Ubuntu 9.10 não pode processar este arquivo.

Como faço para lidar com esse arquivo? Meu objetivo final é aprimorar as linhas 45000000 e 45000100.

    
por nicorellius 21.02.2012 / 00:59

4 respostas

11

Você deve usar sed .

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

Isso diz a sed para imprimir as linhas 45000000-45000100, inclusive, e para sair na linha 45000101.

    
por 21.02.2012 / 02:01
4

Crie um banco de dados MySQL com uma única tabela que tenha um único campo. Em seguida, importe seu arquivo para o banco de dados. Isso tornará muito fácil procurar uma determinada linha.

Eu não acho que mais nada poderia ser mais rápido (se head e tail já falharem). No final, o aplicativo que deseja encontrar a linha n precisa procurar por todo o arquivo até encontrar n newlines. Sem algum tipo de pesquisa (índice de linha para byte offset em arquivo), nenhum melhor desempenho pode ser alcançado.

Dado o quão fácil é criar um banco de dados MySQL e importar dados para ele, eu sinto que essa é uma abordagem viável.

Veja como fazer isso:

DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE 'helperDb';
CREATE TABLE 'helperDb'.'helperTable'( 'lineIndex' BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, 'lineContent' MEDIUMTEXT , PRIMARY KEY ('lineIndex') );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );

/tmp/my_large_file seria o arquivo que você deseja ler.

A sintaxe correta para importar um arquivo com valores delimitados por tabulações em cada linha é:

LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);

Outra grande vantagem disso é que, se você decidir mais tarde extrair outro conjunto de linhas, não precisará esperar horas pelo processamento novamente (a menos que você exclua o banco de dados, é claro).

    
por 21.02.2012 / 01:28
1

Duas boas e velhas ferramentas para arquivos grandes são join e split . Você pode usar a divisão com a opção --lines=<number> que cortou o arquivo em vários arquivos de determinado tamanho.

Por exemplo, split --lines=45000000 huge_file.txt . As partes resultantes seriam em xa, xb, etc. Então você pode head a parte xb que incluiria as linhas que você queria. Você também pode 'juntar' arquivos de volta para um único arquivo grande.

    
por 23.10.2015 / 15:27
0

Você tem as ferramentas certas, mas as usa incorretamente. Como anteriormente respondeu ao U & L, tail -n +X file | head -n Y (observe o + ) é 10-15% mais rápido que sed para linhas Y iniciadas em X. E, convenientemente, você não precisa explicitamente exit do processo como sed .

tail will read and discard the first X-1 lines (there's no way around that), then read and print the following lines. head will read and print the requested number of lines, then exit. When head exits, tail receives a SIGPIPE signal and dies, so it won't have read more than a buffer size's worth (typically a few kilobytes) of lines from the input file.

    
por 16.03.2018 / 20:27

Tags