Jeśli chcesz wiersze od X do Y włącznie (zaczynając od numeracji od 1), użyj
tail -n +$X /path/to/file | head -n $((Y-X+1))
tail
odczyta i odrzuci pierwsze linie X-1 (nie da się tego obejść), a następnie przeczyta i wydrukuje kolejne linie. head
odczyta i wydrukuje żądaną liczbę wierszy, a następnie wyjdzie. Kiedy head
wychodzi, tail
odbiera sygnał SIGPIPE i umiera, więc nie będzie czytał więcej niż rozmiar bufora (zwykle kilka kilobajtów) linii z pliku wejściowego.
Alternatywnie, jak sugeruje gorkypl , użyj sed:
sed -n -e "$X,$Y p" -e "$Y q" /path/to/file
Rozwiązanie sed jest jednak znacznie wolniejsze (przynajmniej w przypadku narzędzi GNU i Busybox; sed może być bardziej konkurencyjny, jeśli wyodrębnisz dużą część pliku w systemie operacyjnym, w którym przesyłanie jest wolne, a sed szybki). Oto krótkie testy porównawcze pod Linuksem; dane zostały wygenerowane przez seq 100000000 >/tmp/a
, środowisko to Linux / amd64, /tmp
jest tmpfs, a maszyna jest bezczynna i nie zamienia się.
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
Jeśli znasz zakres bajtów, z którym chcesz pracować, możesz go szybciej wyodrębnić, przechodząc bezpośrednio do pozycji początkowej. Ale w przypadku linii musisz czytać od początku i liczyć nowe wiersze. Aby wyodrębnić bloki od x włącznie do y wyłącznie od 0, przy rozmiarze bloku b:
dd bs=$b seek=$x count=$((y-x)) </path/to/file