Если вы хотите, чтобы строки от X до Y включали (начиная с нумерации с 1), используйте
tail -n +$X /path/to/file | head -n $((Y-X+1))
tail
прочтет и откажется от первых строк X-1 (обойти это невозможно), затем прочитает и распечатает следующие строки. head
прочтет и распечатает запрошенное количество строк, затем выйдет. Когда head
выходит, tail
получает сигнал SIGPIPE и умирает, поэтому он не будет считывать из входного файла строки размером больше буфера (обычно несколько килобайт).
В качестве альтернативы, как предложил gorkypl , используйте sed:
sed -n -e "$X,$Y p" -e "$Y q" /path/to/file
Решение sed значительно медленнее (по крайней мере, для утилит GNU и Busybox; sed может быть более конкурентоспособным, если вы извлекаете большую часть файла в ОС, где скорость передачи данных медленная, а скорость седа). Вот быстрые тесты под Linux; данные были сгенерированы seq 100000000 >/tmp/a
, среда Linux / amd64, /tmp
tmpfs, и машина в противном случае простаивает и не переставляет.
real user sys command
0.47 0.32 0.12 </tmp/a tail -n +50000001 | head -n 10 #GNU
0.86 0.64 0.21 </tmp/a tail -n +50000001 | head -n 10 #BusyBox
3.57 3.41 0.14 sed -n -e '50000000,50000010 p' -e '50000010q' /tmp/a #GNU
11.91 11.68 0.14 sed -n -e '50000000,50000010 p' -e '50000010q' /tmp/a #BusyBox
1.04 0.60 0.46 </tmp/a tail -n +50000001 | head -n 40000001 >/dev/null #GNU
7.12 6.58 0.55 </tmp/a tail -n +50000001 | head -n 40000001 >/dev/null #BusyBox
9.95 9.54 0.28 sed -n -e '50000000,90000000 p' -e '90000000q' /tmp/a >/dev/null #GNU
23.76 23.13 0.31 sed -n -e '50000000,90000000 p' -e '90000000q' /tmp/a >/dev/null #BusyBox
Если вам известен диапазон байтов, с которым вы хотите работать, вы можете извлечь его быстрее, перейдя непосредственно к начальной позиции. Но для строк, вы должны читать с начала и считать новые строки. Чтобы извлечь блоки от x включительно до y эксклюзивно, начиная с 0, с размером блока b:
dd bs=$b seek=$x count=$((y-x)) </path/to/file