Ожидается, что следующая команда оболочки выведет только нечетные строки входного потока:
echo -e "aaa\nbbb\nccc\nddd\n" | (while true; do head -n 1; head -n 1 >/dev/null; done)
Но вместо этого он просто печатает первую строку: aaa
.
То же самое не происходит, когда он используется с опцией -c
( --bytes
):
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 >/dev/null; done)
Эта команда выводит 1234512345
как ожидалось. Но это работает только в реализации утилиты coreutilshead
. Реализация busybox по- прежнему потребляет лишние символы, поэтому вывод просто 12345
.
Я предполагаю, что этот конкретный способ реализации сделан в целях оптимизации. Вы не можете знать, где заканчивается строка, поэтому вы не знаете, сколько символов вам нужно прочитать. Единственный способ не использовать лишние символы из входного потока - это читать поток побайтно. Но чтение из потока по одному байту за раз может быть медленным. Поэтому я предполагаю, что head
считывает входной поток в достаточно большой буфер и затем считает строки в этом буфере.
Чего нельзя сказать о случае, когда --bytes
используется опция. В этом случае вы знаете, сколько байтов вам нужно прочитать. Таким образом, вы можете прочитать именно это количество байтов и не более того. Реализация corelibs использует эту возможность, но не с busybox , она все же считывает больше байта, чем требуется, в буфер. Вероятно, это сделано для упрощения реализации.
Итак, вопрос. Правильно ли для head
утилиты потреблять больше символов из входного потока, чем было задано? Есть ли какой-то стандарт для утилит Unix? И если есть, то указывает ли это поведение?
PS
Вы должны нажать, Ctrl+C
чтобы остановить команды выше. Утилиты Unix не перестают читать дальше EOF
. Если вы не хотите нажимать, вы можете использовать более сложную команду:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 | [ `wc -c` -eq 0 ] && break >/dev/null; done)
который я не использовал для простоты.