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 catnunca armazena em buffer sua saída. Ele não usa stdioou altera a stdiopolítica de buffer padrão .
Posso ter certeza de que você está usando o GNU cate não algum outro unix catporque os outros não se comportariam dessa maneira. O unix tradicional cattem uma -uopção para solicitar saída sem buffer. O GNU catignora a -uopçã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 catnã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|sedexemplo, trainda está recebendo dados catassim que você pressiona Enter, mas trsegue a stdiopolí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.
sedtambém segue a stdiopolí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 sedbuffer estivesse bloqueando sua saída, você teria que digitar o dobro (para preencher tro buffer de saída e sed a saída) amortecedor).
O GNU sedtem -uopção, portanto, se você reverter a ordem e usá- cat|sed -u|trlo, verá a saída aparecer instantaneamente novamente. (A sed -uopçã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 stdbufque permite alterar o modo de buffer de qualquer comando que use os stdiopadrões. É um pouco frágil, pois é usado LD_PRELOADpara 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'
catbuffer até o stdin fechar.