Існує загальне правило буферизації, яке дотримується стандартна бібліотека вводу-виводу C ( stdio), якою користуються більшість програм Unix. Якщо вихід збирається до терміналу, він видається в кінці кожного рядка; інакше він змивається лише тоді, коли буфер (8K в моїй системі Linux / amd64; у вашій може бути різний) заповнений.
Якщо всі ваші утиліти слідували загальним правилом, ви побачите вихід з затримкою у всіх ваших прикладах ( cat|sed, cat|trі cat|tr|sed). Але є виняток: GNU catніколи не буферизує свій вихід. Він або не використовує, stdioабо змінює stdioполітику буферування за замовчуванням .
Я можу бути впевненим, що ви використовуєте GNU, catа не якийсь інший unix, catоскільки інші не поводитимуться таким чином. У традиційному unix catє -uможливість запитувати небуферний вихід. GNU catігнорує цю -uопцію, оскільки її вихід завжди не буферний.
Отже, коли у вас є труба з a catзліва, в системі GNU пропуск даних по трубі не затримується. catНавіть не збирається через підрядник - ваш термінал робить. Поки ви вводите інформацію для кота, ваш термінал знаходиться в "канонічному" режимі - на основі рядків, з ключами для редагування, такими як backspace та ctrl-U, що пропонує вам можливість редагувати рядок, який ви ввели, перш ніж надсилати його Enter.
У cat|tr|sedприкладі trвсе ще надходять дані, catяк тільки ви натискаєте Enter, але trдотримуєтесь stdioполітики за замовчуванням: його вихід збирається в трубу, тому він не спалахує після кожного рядка. Він записує у другу трубу, коли буфер заповнений або коли приймається EOF, залежно від того, що відбувається першим.
sedтакож дотримується stdioполітики за замовчуванням, але її вихід збирається до терміналу, тому він запише кожен рядок, як тільки закінчиться з ним. Це впливає на те, скільки потрібно ввести до того, як щось з’явиться на іншому кінці трубопроводу - якщо sedблокування його виводу блокувало, вам доведеться набрати вдвічі більше (щоб заповнити trвихідний буфер і sed вихід буфер).
У GNU sedє -uопція, тож якщо ви скасували порядок і використали, cat|sed -u|trви побачите, що вихід з'явиться миттєво знову. ( sed -uОпція може бути доступна в іншому місці, але я не думаю, що це давня традиція Unix на кшталт cat -u) Наскільки я можу сказати, немає еквівалентного варіанту tr.
Існує утиліта, stdbufяка називається, яка дозволяє змінювати режим буферизації будь-якої команди, яка використовує параметри stdioза замовчуванням. Це трохи крихко, оскільки він використовує LD_PRELOADдля досягнення чогось, що бібліотека C не була розроблена для підтримки, але в цьому випадку, здається, працює:
cat | stdbuf -o 0 tr '[:lower:]' '[:upper:]' | sed 'p'
catбуферизація, поки stdin не закриється.