Se você quiser as linhas X a Y inclusive (iniciando a numeração em 1), use
tail -n +$X /path/to/file | head -n $((Y-X+1))
tail
lerá e descartará as primeiras linhas X-1 (não há como contornar isso), depois lerá e imprimirá as seguintes linhas. head
irá ler e imprimir o número solicitado de linhas e sair. Quando head
sai, tail
recebe um sinal SIGPIPE e morre, para que não tenha lido mais do que o tamanho de um buffer (normalmente alguns kilobytes) de linhas do arquivo de entrada.
Como alternativa, como sugerido pelo gorkypl , use sed:
sed -n -e "$X,$Y p" -e "$Y q" /path/to/file
A solução sed é significativamente mais lenta (pelo menos para os utilitários GNU e Busybox; sed pode ser mais competitivo se você extrair grande parte do arquivo em um sistema operacional em que a tubulação é lenta e a sed é rápida). Aqui estão referências rápidas no Linux; os dados foram gerados por seq 100000000 >/tmp/a
, o ambiente é Linux / amd64, /tmp
é tmpfs e a máquina está ociosa e sem troca.
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
Se você conhece o intervalo de bytes com o qual deseja trabalhar, pode extraí-lo mais rapidamente, pulando diretamente para a posição inicial. Mas para linhas, você precisa ler desde o início e contar novas linhas. Para extrair blocos de x inclusive para exclusivo y começando em 0, com um tamanho de bloco de b:
dd bs=$b seek=$x count=$((y-x)) </path/to/file