Bash вытащить определенные строки из файла

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

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

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

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

Ответы

Ответ 1

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

sed -n '100000,125000p' input

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

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

Ответ 2

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

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

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

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

ИЗМЕНИТЬ: предложение @glenn jackman (см. комментарий)

Ответ 3

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

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 parallel.

Ответ 4

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

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

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

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

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

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