Si desea líneas X a Y inclusive (comenzando la numeración en 1), use
tail -n +$X /path/to/file | head -n $((Y-X+1))
tail
leerá y descartará las primeras líneas X-1 (no hay forma de evitarlo), luego leerá e imprimirá las siguientes líneas. head
leerá e imprimirá el número de líneas solicitado, luego saldrá. Cuando head
sale, tail
recibe una señal SIGPIPE y muere, por lo que no habrá leído más del tamaño de un búfer (generalmente unos pocos kilobytes) de líneas del archivo de entrada.
Alternativamente, como sugirió gorkypl , use sed:
sed -n -e "$X,$Y p" -e "$Y q" /path/to/file
Sin embargo, la solución sed es significativamente más lenta (al menos para las utilidades GNU y Busybox; sed podría ser más competitiva si extrae una gran parte del archivo en un sistema operativo donde la tubería es lenta y sed es rápida). Aquí hay puntos de referencia rápidos en Linux; los datos fueron generados por seq 100000000 >/tmp/a
, el entorno es Linux / amd64, /tmp
es tmpfs y la máquina está inactiva y no se intercambia.
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
Si conoce el rango de bytes con el que desea trabajar, puede extraerlo más rápido saltando directamente a la posición inicial. Pero para las líneas, debe leer desde el principio y contar las nuevas líneas. Para extraer bloques de x inclusive a y exclusivo a partir de 0, con un tamaño de bloque de b:
dd bs=$b seek=$x count=$((y-x)) </path/to/file