Istnieje ogólna reguła buforowania, po której następuje standardowa biblioteka C we / wy ( stdio
) używana przez większość programów uniksowych. Jeśli wyjście trafia do terminala, jest opróżniane na końcu każdej linii; w przeciwnym razie jest opróżniany tylko wtedy, gdy bufor (8 KB na moim systemie Linux / amd64; może być inny na twoim) jest pełny.
Jeśli wszystkie media były zgodnie z ogólną regułę, że widzisz wyjścia z opóźnieniem wszystkich przykładów ( cat|sed
, cat|tr
, i cat|tr|sed
). Ale jest wyjątek: GNU cat
nigdy nie buforuje swoich danych wyjściowych. Nie używa stdio
lub zmienia domyślną stdio
zasadę buforowania.
Mogę być całkiem pewien, że używasz GNU, cat
a nie jakiegoś innego Uniksa, cat
ponieważ inni nie zachowaliby się w ten sposób. Tradycyjny unix cat
ma -u
opcję żądania niebuforowanych danych wyjściowych. GNU cat
ignoruje tę -u
opcję, ponieważ jej dane wyjściowe są zawsze niebuforowane.
Tak więc, gdy masz rurkę z cat
lewym, w systemie GNU, przepływ danych przez rurę nie będzie opóźniony. cat
Nawet nie będzie wiersz po wierszu - terminal robi to. Podczas wpisywania danych wejściowych dla cat, twój terminal jest w trybie „kanonicznym” - oparty na linii, z klawiszami edycji takimi jak backspace i ctrl-U, oferującymi możliwość edycji linii, którą wpisałeś przed wysłaniem Enter.
W tym cat|tr|sed
przykładzie tr
nadal odbiera dane, cat
gdy tylko naciśniesz Enter, ale tr
postępuje zgodnie z stdio
domyślną zasadą: jego wyjście przechodzi do potoku, więc nie opróżnia się po każdej linii. Zapisuje do drugiego potoku, gdy bufor jest pełny lub po otrzymaniu EOF, w zależności od tego, co nastąpi wcześniej.
sed
postępuje również zgodnie z stdio
domyślną polityką, ale jego dane wyjściowe trafiają do terminala, więc zapisze każdą linię, gdy tylko się z nią skończy. Wpływa to na to, ile musisz wpisać, zanim coś pojawi się na drugim końcu potoku - jeśli sed
buforowanie blokowe jego danych wyjściowych, musisz wpisać dwa razy więcej (aby wypełnić tr
bufor wyjściowy i sed
dane wyjściowe bufor).
GNU sed
ma -u
opcję, więc jeśli odwrócisz kolejność i cat|sed -u|tr
użyjesz, zobaczysz, że dane wyjściowe pojawią się ponownie. (Ta sed -u
opcja może być dostępna gdzie indziej, ale nie sądzę, że jest to starożytna tradycja uniksowa taka jak cat -u
). O ile wiem, nie ma równoważnej opcji tr
.
Istnieje narzędzie o nazwie, stdbuf
które pozwala zmienić tryb buforowania każdego polecenia, które korzysta z stdio
wartości domyślnych. Jest to trochę kruche, ponieważ wykorzystuje się LD_PRELOAD
do osiągnięcia czegoś, co biblioteka C nie została zaprojektowana do obsługi, ale w tym przypadku wydaje się działać:
cat | stdbuf -o 0 tr '[:lower:]' '[:upper:]' | sed 'p'
cat
buforuje się aż do zamknięcia standardowego wejścia.