Ordem de substituição do processo `tee` e `bash`

Ordem de substituição do processo `tee` e `bash`

Eu teria suposto que esse código teria impresso "ah" primeiro:

echo foo | tee >(rev) | ( sleep 1 ; cat ; )

Saída:

foo
oof

Aumentar o sleeptempo não altera a ordem. Por que isso não funciona?


Observe que outras ferramentasfazertrabalhar como deveria,por exemplo: echo foo | pee rev 'sleep 1 ; cat'.

Responder1

Em

echo foo | tee >(rev) | (sleep 1; cat)

Assim bashcomo em ksh, mas ao contrário de zsh, o stdout de revtambém é o canal para (sleep 1; cat).

echo, teee revo (...)subshell são iniciados ao mesmo tempo, mas teegravam foo\nem stdoutanteso pipe to rev, portanto, em qualquer caso, revescreverá oofno pipe depois de teewrites foo, portanto oofsó pode vir por último. Atrasar catnão tem incidência.

Se você quisesse a saída derev nãopara passar pelo cano até (sleep 1; cat), você usaria zshou faria:

{ echo foo 3>&- | tee >(rev >&3 3>&-) 3>&- | (sleep 1; cat) 3>&-; } 3>&1

Observe que zshtambém possui um recurso integrado tee, multiospara que você possa fazer:

echo foo > >(rev) > >(sleep 1; cat)

No entanto em:

echo foo > >(rev) | (sleep 1; cat)

A saída de revpassaria cat(o que é confuso, considerando que não é o echo foo >(echo bar) | (sleep 1; cat)caso).

Responder2

Usar duas bashsubstituições de processo (em vez de apenas uma e depois um canal) e depois despejar o STDOUT em /dev/null funciona conforme o esperado:

echo foo | tee >(rev) >( sleep 1 ; cat ; ) > /dev/null ; sleep 1

Saída:

oof
foo

Notas:

  • o sleepimpede "foo" seja impresso após o prompt de comando.
  • reduzir o sleepnúmero de atraso para um valor ideal deveria ser melhor, mas não tenho certeza de qual deveria ser esse número. 1é um pouco lento, mas sempre parece funcionar; .01nem sempre funciona (ou seja, a saída às vezes está na ordem errada) .1parece funcionar bem.

informação relacionada