13

У меня проблема с просмотром фрагментов очень большого текстового файла. Этот файл, размером примерно 19 ГБ, очевидно, слишком велик для просмотра любыми традиционными способами.

Я попробовал head 1 и tail 1 (head -n 1 и tail -n 1) с обеими командами, соединенными по-разному (чтобы получить кусок в середине) без удачи. Моя Linux-машина с Ubuntu 9.10 не может обработать этот файл.

Как мне обработать этот файл? Моя конечная цель - отточить линии 45000000 и 45000100.

4 ответа4

11

Вы должны использовать sed .

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

Это говорит sed для печати строк 45000000-45000100 включительно и выхода из строки 45000101.

4

Создайте базу данных MySQL с одной таблицей, которая имеет одно поле. Затем импортируйте ваш файл в базу данных. Это позволит легко найти определенную строку.

Я не думаю, что что-то еще может быть быстрее (если head и tail уже сломались). В конце концов, приложение, которое хочет найти строку n , должно выполнить поиск по всему файлу, пока не найдет n новых строк. Без какого-либо поиска (строковый индекс к байтовому смещению в файл) невозможно добиться лучшей производительности.

Учитывая, как легко создать базу данных MySQL и импортировать в нее данные, я чувствую, что это жизнеспособный подход.

Вот как это сделать:

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 будет файлом, который вы хотите прочитать.

Правильный синтаксис для импорта файла с разделенными табуляцией значениями в каждой строке:

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

Еще одним важным преимуществом этого является то, что, если вы решите позднее извлечь другой набор строк, вам не придется ждать часами обработки снова (если, конечно, вы не удалите базу данных).

1

Два старых добрых инструмента для больших файлов - это join и split . Вы можете использовать параметр split с параметром --lines=<number> чтобы разрезать файл на несколько файлов определенного размера.

Например, split --lines=45000000 huge_file.txt . Приведённые части будут находиться в Xa, хь и т.д. Тогда вы можете head часть XB , которая будет включать в себя строку , которые вы хотели. Вы также можете «объединить» файлы обратно в один большой файл.

0

У вас есть нужные инструменты, но вы используете их неправильно. Как уже было сказано ранее в U & L, tail -n +X file | head -n Y (обратите внимание на +) на 10-15% быстрее, чем sed для линий Y, начинающихся с X. И удобно, вам не нужно явно exit из процесса, как с sed .

tail будет читать и отбрасывать первые строки X-1 (пути назад нет), затем читать и печатать следующие строки. head прочитает и напечатает требуемое количество строк, затем выйдет. Когда заголовок выходит, tail получает сигнал SIGPIPE и умирает, поэтому он не будет считывать из входного файла строки размером больше буфера (обычно несколько килобайт).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .