Existe uma regra geral de armazenamento em buffer seguida pela biblioteca de E / S padrão C ( stdio
) usada pela maioria dos programas unix. Se a saída estiver indo para um terminal, ela será liberada no final de cada linha; caso contrário, ele será liberado apenas quando o buffer (8K no meu sistema Linux / amd64; pode ser diferente no seu) estiver cheio.
Se todas as suas utilidades estavam seguindo a regra geral, você veria saída com atraso em todos os seus exemplos ( cat|sed
, cat|tr
, e cat|tr|sed
). Mas há uma exceção: o GNU cat
nunca armazena em buffer sua saída. Ele não usa stdio
ou altera a stdio
política de buffer padrão .
Posso ter certeza de que você está usando o GNU cat
e não algum outro unix cat
porque os outros não se comportariam dessa maneira. O unix tradicional cat
tem uma -u
opção para solicitar saída sem buffer. O GNU cat
ignora a -u
opção porque sua saída é sempre sem buffer.
Portanto, sempre que você tiver um canal com um cat
à esquerda, no sistema GNU, a passagem de dados pelo canal não será atrasada. O cat
não está mesmo indo linha por linha - o terminal está fazendo isso. Enquanto você digita a entrada para gato, seu terminal está no modo "canônico" - baseado em linha, com teclas de edição como backspace e ctrl-U, oferecendo a você a chance de editar a linha que você digitou antes de enviá-la Enter.
No cat|tr|sed
exemplo, tr
ainda está recebendo dados cat
assim que você pressiona Enter, mas tr
segue a stdio
política padrão: sua saída está indo para um canal, para que não seja liberada após cada linha. Ele grava no segundo canal quando o buffer está cheio ou quando um EOF é recebido, o que ocorrer primeiro.
sed
também segue a stdio
política padrão, mas sua saída está indo para um terminal, para que ele escreva cada linha assim que terminar. Isso afeta o quanto você deve digitar antes que algo apareça na outra extremidade do pipeline - se o sed
buffer estivesse bloqueando sua saída, você teria que digitar o dobro (para preencher tr
o buffer de saída e sed
a saída) amortecedor).
O GNU sed
tem -u
opção, portanto, se você reverter a ordem e usá- cat|sed -u|tr
lo, verá a saída aparecer instantaneamente novamente. (A sed -u
opção pode estar disponível em outro lugar, mas eu não acho que seja uma tradição antiga do unix cat -u
). Até onde eu sei, não há uma opção equivalente tr
.
Existe um utilitário chamado stdbuf
que permite alterar o modo de buffer de qualquer comando que use os stdio
padrões. É um pouco frágil, pois é usado LD_PRELOAD
para realizar algo que a biblioteca C não foi projetada para oferecer suporte, mas, neste caso, parece funcionar:
cat | stdbuf -o 0 tr '[:lower:]' '[:upper:]' | sed 'p'
cat
buffer até o stdin fechar.