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 1234512345wie erwartet ausgegeben. Dies funktioniert jedoch nur in der coreutils- Implementierung des headDienstprogramms. 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 headder 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 --bytesOption 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 headDienstprogramm 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.