Comportamento de “eval” em “set -e” na expressão condicional

Comportamento de “eval” em “set -e” na expressão condicional

Considere os comandos

eval false || echo ok
echo also ok

Normalmente, esperaríamos que isso executasse o falseutilitário e, como o status de saída é diferente de zero, executasse echo okand echo also ok.

Em todos os shells do tipo POSIX que eu uso ( ksh93, zsh, bash, dash, OpenBSD kshe yash), é isso que acontece, mas as coisas ficam interessantes se habilitarmos set -e.

Se set -eestiver em vigor, o OpenBSD she kshos shells (ambos derivados de pdksh) encerrarão o script ao executar o eval. Nenhum outro shell faz isso.

POSIX dizque um erro em um utilitário especial integrado (como eval) deve fazer com que o shell não interativo seja encerrado. Não tenho certeza se a execução falseconstitui "um erro" (se fosse, seria independente de set -eestar ativo).

A maneira de contornar isso parece ser colocar o evalem um subshell,

( eval false ) || echo ok
echo also ok

A questão é se devo fazer isso em um script de shell correto para POSIX ou se é um bug no shell do OpenBSD? Além disso, o que significa “erro” no texto POSIX vinculado acima?


Informação extra: Os shells do OpenBSD executarão echo okambos com e sem set -e no comando

eval ! true || echo ok

Meu código original parecia

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi

qual serianãosaída not okusando string=falseos shells do OpenBSD (isso seria encerrado), e eu não tinha certeza se era intencional, por engano ou por mal-entendido, ou qualquer outra coisa.

Responder1

O fato de nenhum outro shell precisar de tal solução alternativa é uma forte indicação de que é um bug no OpenBSD ksh. Na verdade, o ksh93 não apresenta esse problema.

A existência de um ||na linha de comando deve evitar a saída do shell causada por um código de retorno 1 no lado esquerdo dele.

O erro de umespecialembutido deve causar a saída de um shell não interativode acordo com POSIXmas isso nem sempre é verdade. Tentar continuesair de um loop é um erro e continueé um erro interno. Mas a maioria dos shells não sai em:

continue 3

Um builtin que emite um erro claro, mas não sai.

Portanto, a saída ativada falseé gerada pela set -econdição e não pela característica interna do comando ( evalneste caso).

As condições exatas em que set -edeve sair são bem mais confusas no POSIX.

Responder2

[desculpe se esta não é uma resposta real, vou atualizá-la quando chegar a hora]

Dei uma olhada no código-fonte e minhas conclusões são:

1) É um bug/limitação, nada filosófico por trás disso.

2) A "correção" do fork portátil do ksh ( mksh) do OpenBSD émuitopobre, só piorando as coisas, sem realmente consertar:

Novo bug, diferente de todos os outros shells:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

Ainda não foi realmente corrigido:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

Você pode substituir bashacima por dash, zsh, yash, ksh93, etc.

informação relacionada