Se si desidera includere le linee da X a Y (iniziando la numerazione da 1), utilizzare
tail -n +$X /path/to/file | head -n $((Y-X+1))
tail
leggerà e scarterà le prime righe X-1 (non c'è modo di aggirarle), quindi leggerà e stamperà le seguenti righe. head
leggerà e stamperà il numero di righe richiesto, quindi uscirà. Quando head
esce, tail
riceve un segnale SIGPIPE e muore, quindi non avrà letto più del valore di una dimensione del buffer (in genere pochi kilobyte) di righe dal file di input.
In alternativa, come suggerito Gorkypl , usa sed:
sed -n -e "$X,$Y p" -e "$Y q" /path/to/file
La soluzione sed è significativamente più lenta (almeno per le utility GNU e le utility Busybox; sed potrebbe essere più competitiva se si estrae gran parte del file su un sistema operativo in cui le tubazioni sono lente e sed è veloce). Ecco alcuni benchmark rapidi sotto Linux; i dati sono stati generati seq 100000000 >/tmp/a
, l'ambiente è Linux / amd64, /tmp
è tmpfs e la macchina è altrimenti inattiva e non scambia.
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 conosci l'intervallo di byte con cui vuoi lavorare, puoi estrarlo più velocemente saltando direttamente alla posizione iniziale. Ma per le righe, devi leggere dall'inizio e contare le nuove righe. Per estrarre i blocchi da x inclusivo a y esclusivo a partire da 0, con una dimensione del blocco di b:
dd bs=$b seek=$x count=$((y-x)) </path/to/file