Você pode usar a substituição de processos diretamente nos redirecionamentos:
gen > >(one) 2> >(two)
Isso fornecerá a saída padrão de gen
como entrada padrão para one
e o erro padrão de gen
como entrada para two
. Aqueles poderiam ser comandos executáveis ou funções; aqui estão as funções que usei:
one() {
while read line
do
echo $'\e[31m'"$line"$'\e[22m'
done
}
two() {
while read line
do
echo $'\e[32m'"$line"$'\e[22m'
echo "$line" >&2
done
}
Eles exibem suas linhas de entrada em vermelho e verde, respectivamente, e two
também grava no erro padrão comum. Você pode fazer o que quiser dentro dos loops ou enviar a entrada para outro programa ou o que for necessário.
Observe que não existe realmente algo como "preservando a ordem da linha" quando você está nesse ponto - eles são dois fluxos separados e processos separados, e é bem possível que o agendador seja executado um processo por um tempo antes que ele dê o outro, com os dados mantidos no buffer do kernel até que ele seja lido. Eu tenho usado uma função de saída de números ímpares para stdout e até mesmo para stderr para testar, e é comum obter uma série de uma dúzia ou mais em uma linha de cada.
Seria possível obter algo mais próximo da ordem que aparece no terminal, mas provavelmente não no Bash. Programa de AC usando pipe
e select
poderia reconstruir uma ordenação (embora ainda não seja garantida a mesma exibição, pelo mesmo motivo: seu processo pode não estar programado por um tempo e uma vez que há um backlog, não há como dizer o que veio primeiro 1 ). Se a ordenação for de importância vital, você precisará de outra abordagem e, provavelmente, da cooperação do executável de base. Se for um requisito difícil, talvez seja necessário reconsiderar.
1 Também pode haver métodos específicos da plataforma para controlar o buffer de tubulação, mas é improvável que eles também o ajudem bastante. No Linux, você pode reduzir o tamanho do buffer tão baixo quanto o tamanho da página do sistema, mas não menor. Não conheço um que permita forçar gravações imediatamente (ou bloquear até que sejam lidas). Em qualquer caso, eles poderiam ser armazenados em buffer no final da fonte na forma de fluxos de stdio e, em seguida, você nunca veria um pedido.