Il seguente comando shell doveva stampare solo le righe dispari del flusso di input:
echo -e "aaa\nbbb\nccc\nddd\n" | (while true; do head -n 1; head -n 1 >/dev/null; done)
Ma invece si limita a stampare la prima riga: aaa
.
Lo stesso non accade quando viene utilizzato con l' opzione -c
( --bytes
):
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 >/dev/null; done)
Questo comando viene emesso 1234512345
come previsto. Ma questo funziona solo nel coreutils attuazione del head
programma di utilità. L' implementazione di busybox consuma ancora caratteri extra, quindi l'output è giusto 12345
.
Immagino che questo specifico modo di implementazione sia fatto a fini di ottimizzazione. Non puoi sapere dove finisce la linea, quindi non sai quanti caratteri devi leggere. L'unico modo per non utilizzare caratteri aggiuntivi dal flusso di input è leggere il flusso byte per byte. Ma la lettura dallo stream di un byte alla volta potrebbe essere lenta. Quindi immagino che head
legge il flusso di input su un buffer abbastanza grande e quindi conti le righe in quel buffer.
Lo stesso non si può dire per il caso in cui --bytes
si utilizza l'opzione. In questo caso sai quanti byte devi leggere. Quindi puoi leggere esattamente questo numero di byte e non di più. L' implementazione di corelibs sfrutta questa opportunità, ma quella di busybox no, legge ancora più byte di quanto richiesto in un buffer. Probabilmente viene fatto per semplificare l'implementazione.
Quindi la domanda. È corretto che l' head
utilità consumi più caratteri dal flusso di input di quanto non sia stato chiesto? Esiste una sorta di standard per le utility Unix? E se esiste, specifica questo comportamento?
PS
Devi premere Ctrl+C
per interrompere i comandi sopra. Le utility Unix non mancano di leggere oltre EOF
. Se non si desidera premere, è possibile utilizzare un comando più complesso:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 | [ `wc -c` -eq 0 ] && break >/dev/null; done)
che non ho usato per semplicità.