bash вытащить определенные строки из файла - PullRequest
16 голосов
/ 25 июля 2011

Мне было интересно, есть ли более эффективный способ выполнить эту задачу.Я работаю с файлами с числом строк от нескольких сотен тысяч до пары миллионов.Скажем, я знаю, что строки 100 000 - 125 000 - это строки, которые содержат данные, которые я ищу.Я хотел бы знать, есть ли быстрый способ извлечь только эти нужные строки из файла.Прямо сейчас я использую цикл с grep следующим образом:

 for ((i=$start_fid; i<=$end_fid; i++))
  do
    grep "^$i " fulldbdir_new >> new_dbdir${bscnt}
  done

, который работает нормально, просто это занимает больше времени, чем хотелось бы.И строки содержат больше, чем просто цифры.В основном каждая строка имеет около 10 полей, первое из которых представляет собой последовательное целое число, которое появляется только один раз для каждого файла.

Мне удобно писать на С, если необходимо.

Ответы [ 4 ]

22 голосов
/ 25 июля 2011

sed может выполнять работу ...

sed -n '100000,125000p' input

РЕДАКТИРОВАТЬ: Согласно предложению Гленна Джекмана, может быть скорректирована таким образом для эффективности ...

sed -n '100000,125000p; 125001q' input

5 голосов
/ 25 июля 2011

Я бы использовал awk:

awk 'NR >= 100000; NR == 125000 {exit}' file

Для больших чисел вы также можете использовать E обозначение :

awk 'NR >= 1e5; NR == 1.25e5 {exit}' file

РЕДАКТИРОВАТЬ: предложение @glenn Jackman (см. Комментарий)

2 голосов
/ 25 июля 2011

Вы можете попробовать комбинацию хвоста и головы, чтобы получить правильные линии.

head -n 125000 file_name | tail -n 25001 | grep "^$i "

Не забывайте и Perl.

perl -ne 'print if $. >= 100000 && $. <= 125000' file_name | grep "^$i "

или более быстрый Perl:

perl -ne 'print if $. >= 100000; exit() if $. >= 100000 && $. <= 125000' | grep "^$i "

Кроме того, вместо цикла for вы можете захотеть использовать GNU параллельно .

0 голосов
/ 26 июля 2011

Ответы пока читают первые 100000 строк и отбрасывают их.Поскольку дисковый ввод-вывод часто является ограничивающим фактором в наши дни, было бы неплохо иметь решение, которое не должно считывать нежелательные строки.

Если первые 100000 строк всегда имеют одинаковую общую длину (приблизительно)Затем вы можете вычислить, как далеко искать файл, чтобы добраться примерно до строки 100000, а затем прочитать следующие 25000 строк.Возможно, прочитайте еще немного до и после, чтобы убедиться, что у вас есть все 25000 строк.

Вы не знаете точно, на какой линии вы находитесь, что может или не может быть важным для вас.

Предположим, что средняя длина строки первых 100000 строк равна 130, тогда вы получите что-то вроде этого:

 dd if=the_file skip=130 bs=100000 | head -n 25000

Вам придется выбросить первую строку, так как она может быть только наполовину.линия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...