Эффективный способ получить n средних строк из очень большого файла

У меня есть большой файл около 60 ГБ.

Мне нужно получить n средних строк файла. Я использую команду с головой и хвостом, например

tail -m file |head -n >output.txt
where m,n are numbers

Общая структура файла показана ниже с набором записей (столбцы, разделенные запятыми). Каждая строка может иметь разную длину (скажем, не более 5000 символов).

col1,col2,col3,col4...col10

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


person Mahesh    schedule 09.12.2013    source источник
comment
Можете ли вы рассказать нам больше о данных в вашем файле, например, об общей структуре файла. Как разделены строки? Максимальный размер каждой строки? чтобы мы могли попытаться перейти в память к нужной строке напрямую? Если ваши строки не равны по длине, нам придется разобрать их посимвольно. В этом случае вы уже используете наилучший возможный способ.   -  person Ashis Kumar Sahoo    schedule 09.12.2013
comment
Добавил в вопрос общую структуру записи.   -  person Mahesh    schedule 09.12.2013


Ответы (5)


С помощью sed вы можете хотя бы удалить конвейер:

sed -n '600000,700000p' file > output.txt

напечатает строки с 600000 по 700000.

person perreal    schedule 09.12.2013
comment
Если есть много строк после последней запрошенной строки, может помочь также добавить команду 'q': sed -n '600000,700000p;700000q' file. В противном случае sed будет продолжать работать до тех пор, пока не будет прочитана последняя строка файла (даже если ничего не будет напечатано). - person geronimo; 20.03.2019

awk 'FNR>=n && FNR‹=m'

за которым следует имя файла.

person Anitha Mani    schedule 09.12.2013

Возможно, более эффективно использовать утилиту split, потому что с tail и head в канале вы сканируете некоторые части файла дважды.

Пример

split -l <k> <file> <prefix>

Где k — это количество строк, которые вы хотите иметь в каждом файле, а (необязательно) prefix добавляется к имени каждого выходного файла.

person Rajish    schedule 09.12.2013
comment
да, я думал об использовании этой команды, но на моей машине не так много места для хранения разделенных файлов :( - person Mahesh; 09.12.2013

Единственное возможное решение, которое я могу придумать для ускорения поиска, - это построить и проиндексировать ваши строки, что-то вроде:

 0 00000000
 1 00000013
 2 00000045
   ...
 N 48579344

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

Очевидно, что каноническим решением такой проблемы было бы хранение данных в БД (см., например, SQLite), не в обычном файле... :-)

person MarcoS    schedule 09.12.2013
comment
Я намерен переместить эти данные в БД. Поскольку некоторые записи имеют неправильную структуру и из-за некоторых других проблем, я перемещаю их в БД по частям. - person Mahesh; 09.12.2013

Откройте файл в режиме двоичного произвольного доступа, ищите в середине, двигайтесь вперед последовательно, пока не достигнете \n или \n\r ascii, начиная со следующего символьного дампа N строк в ваш оставшийся файл (один \n - одна строка) . Дело сделано.

Если ваш файл отсортирован и вам нужны данные между двумя ключами, вы используете описанный выше метод + деление пополам.

person bobah    schedule 09.12.2013