Der folgende Shell-Befehl sollte nur ungerade Zeilen des Eingabestreams ausgeben:
echo -e "aaa\nbbb\nccc\nddd\n" | (while true; do head -n 1; head -n 1 >/dev/null; done)
Aber anstatt es druckt nur die erste Zeile: aaa
.
Dasselbe passiert nicht, wenn es mit der Option -c
( --bytes
) verwendet wird:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 >/dev/null; done)
Dieser Befehl wird 1234512345
wie erwartet ausgegeben. Dies funktioniert jedoch nur in der coreutils- Implementierung des head
Dienstprogramms. Bei der Belegtbox- Implementierung werden immer noch zusätzliche Zeichen verwendet, sodass die Ausgabe gerecht ist 12345
.
Ich denke, diese spezielle Art der Implementierung dient Optimierungszwecken. Sie können nicht wissen, wo die Zeile endet, sodass Sie nicht wissen, wie viele Zeichen Sie lesen müssen. Die einzige Möglichkeit, keine zusätzlichen Zeichen aus dem Eingabestream zu verbrauchen, besteht darin, den Stream Byte für Byte zu lesen. Das Lesen eines Bytes aus dem Stream kann jedoch langsam sein. Ich vermute also, dass head
der Eingabestream in einen ausreichend großen Puffer eingelesen wird und dann die Zeilen in diesem Puffer gezählt werden.
Dies gilt nicht für den Fall, dass die --bytes
Option verwendet wird. In diesem Fall wissen Sie, wie viele Bytes Sie lesen müssen. Sie können also genau diese Anzahl von Bytes und nicht mehr lesen. Die corelibs- Implementierung nutzt diese Gelegenheit, die busybox jedoch nicht. Sie liest immer noch mehr Byte als erforderlich in einen Puffer. Dies wird wahrscheinlich zur Vereinfachung der Implementierung durchgeführt.
Also die Frage. Ist es richtig, dass das head
Dienstprogramm mehr Zeichen aus dem Eingabestream verbraucht, als angefordert wurden? Gibt es einen Standard für Unix-Dienstprogramme? Und wenn ja, gibt es dieses Verhalten an?
PS
Sie müssen drücken Ctrl+C
, um die obigen Befehle zu stoppen. Die Unix-Dienstprogramme schlagen beim Lesen darüber hinaus nicht fehl EOF
. Wenn Sie nicht drücken möchten, können Sie einen komplexeren Befehl verwenden:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 | [ `wc -c` -eq 0 ] && break >/dev/null; done)
was ich der Einfachheit halber nicht benutzt habe.