Існує загальне правило буферизації, яке дотримується стандартна бібліотека вводу-виводу 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 не закриється.