Existe uma maneira de reescrever a estrutura de comando A && B || C | D
para que B ou C seja canalizado para D?
Com o comando atual, apenas B ou C e D são executados.
Por exemplo:
Existe uma maneira de reescrever a estrutura de comando A && B || C | D
para que B ou C seja canalizado para D?
Com o comando atual, apenas B ou C e D são executados.
Por exemplo:
Respostas:
Sim, no bash você pode usar parênteses:
(A && B || C) | D
Dessa forma, a saída de A && B || C
será canalizada D
.
sh
:)
A
está dentro da subcamada, este também inclui A
.)
Você pode escrever isso como
if A; then B; else C; fi | D
Você diz que deseja executar um B
ou outro C
, mas A && B || C
não consegue isso. Se A
for bem-sucedido, mas for B
executado e falhar, ele será executado C
.
Nota 1: se você, de alguma forma, pode garantir que B
sempre seja bem-sucedido e queira continuar com uma versão curta, eu ainda optaria por
{ A && B || C; } | D
acabou ( ... )
, pois o último força desnecessariamente a criação de um novo subshell, que pode ou não ser otimizado.
Nota 2: ambas as formas assumem que A
não produz saída, o que é verdade no seu exemplo, mas não necessariamente no geral. Isso pode ser evitado por
A; if [ "$?" -eq 0 ]; then B; else C; fi | D
{ … }
não força a criação de um subshell devido ao pipe? I observar o seguinte comportamento: pgrep bash
e pgrep bash | cat
e if true; then pgrep bash; fi
e { pgrep bash; }
têm uma linha de saída; ( pgrep bash; )
e ( pgrep bash; ) | cat
e { pgrep bash; } | cat
e if true; then pgrep bash; fi | cat
tem duas linhas de saída.
... | ...
faz com que um subshell seja criado, isso é inevitável. ( ... )
, pelo menos em teoria, faz com que seja criado um subshell adicional que { ...; }
evite, mas é isso que eu quis dizer com "pode ou não ser otimizado": é possível que, nesse caso em particular, o shell perceba que não importa, o efeito seria o mesmo.
A resposta do aceitador está correta, mas não cobre o caso de uso potencial para não ter a saída A
como entrada de D
. Para conseguir isso, você precisará de um redirecionamento de fluxo, A
dependendo de suas necessidades.
Se você deseja descartar a saída de A
qualquer maneira:
{ A >/dev/null && B || C; } | D
Se você deseja ver a saída do A
terminal:
{ A >/dev/tty && B || C; } | D
Se você precisar da saída A
como entrada de um comando subsequente, E
precisará de um grupo de comandos adicional e redirecionamento de fluxo:
{ { A >&3 && B || C; } | D; } 3>&1 | E
Se tudo isso parecer muito misterioso para você (como para mim), recomendo que você use a variável especial do shell para o status de saída A
e trabalhe com isso:
A
if [ $? -eq 0 ]; then
B
else
C
fi |
D
Se você quer ser mais conciso, mas não muito misterioso, sugiro o seguinte:
A; { [ $? -eq 0 ] && B || C; } | D
(Veja também a última parte da resposta do hvd que eu não notei quando escrevi minha resposta original.)
A
saí do pipeline.
A && (B || C) | D
, se você não quer B, C ou D para ser executado quando uma falha