Bloco de execução condicional com || e parênteses problema

4

Então, isso deve ser simples. Estou tentando testar uma condição no topo de um script e sair do roteiro inteiro quando a condição falha, e tenho duas declarações que quero executar quando resgatar. Com um único exit e nenhuma segunda instrução, tudo bem, mas não importa como eu adicione uma segunda instrução, não consigo sair completamente. A regra cosmética implícita é que isso deve ser tudo em uma linha. Eu descobri isso quando esta mudança de uma linha para um script não funcionou como pretendido. O roteiro continuou.

Primeiro, deixe-me mostrar o que funciona . A linha a seguir será encerrada se a variável $ USER não for 'x' e isso é bom. Eu sei que isso funciona porque a digitação dessa linha em uma janela de terminal fechará essa janela de terminal (a menos que seu ID de usuário seja realmente 'x'), então está realmente fazendo uma saída de nível superior:

[ $USER = 'x' ] || exit 1

Então, isso é bom e exatamente como eu quero, exceto que quero repetir uma mensagem antes de sair; no entanto, se eu tentar adicionar o eco, a saída não ocorrerá mais ou, em vez disso, parece ocorrer "diferente", como talvez em um contexto de função bash ou algo assim. A próxima linha não fecha seu terminal, e isso é ruim.

[ $USER = 'x' ] || (echo "Time to bail" ; exit 1)

Eu pensei que talvez o ponto-e-vírgula estivesse sendo comido pelo eco, mas não, a saída parece estar sendo atingida. Como eu sei? Eu mudei o código acima e depois ecoei $? e eu vi qualquer valor que coloquei onde você vê "1" acima. E é claro que eu estava vendo esses valores em uma janela de terminal que queria ser fechada e não estava fechada.

A próxima variação também mostra uma segunda maneira de executar um eco e uma segunda instrução, mas novamente o mesmo comportamento ocorre quando uma saída é usada:

[ $USER = 'x' ] || (echo "Time to bail" && exit 1)

Espero que alguém aqui faça tudo isso não apenas não estranho, mas sensato.

Então, isso não é possível em uma linha?

( bash --version : GNU bash, version 4.3.30(1)-release )

    
por user62177541 21.10.2015 / 07:52

2 respostas

5

O que você está procurando é algo assim:

[ "$USER" = "x" ] || { echo "Time to bail"; exit 1; }

A instrução { list; } executa os comandos na lista fornecida no contexto atual da shell. Nenhum subshell é criado, diferentemente da notação ( list ) . Uma chamada exit entre parênteses sairá dessa sub-linha e não da própria shell pai.

Os exemplos em sua pergunta com a declaração if em uma linha ou várias linhas estão sintaticamente corretos. Eu não posso reproduzir esse comportamento. Não importa quantas linhas haja; a declaração if nunca inicia uma subcamada em seu corpo.

BTW: Eu adicionei aspas duplas à variável na condição, porque quando a variável $USER está vazia, a construção se expandirá para [ = "x" ] , o que não é válido. Com aspas duplas, ele expande para [ "" = "x" ] .

    
por 21.10.2015 / 08:17
0

Graças à sugestão de @ mikeserv, a resposta é extraordinariamente simples e tem a ver com a importância de reconhecer que os parênteses apresentam um tipo muito especial de agrupamento. Parênteses criam uma sub-casca, e é exatamente por isso que eu estava vendo a falta do que eu chamei de saída de "nível superior".

Uma explicação completa é aqui , e aqui está o trecho principal:

Placing a list of commands between parentheses causes a subshell environment to be created... Placing a list of commands between curly braces causes the list to be executed in the current shell context.

O que é um pouco desagradável aqui é que os dois não são completamente intercambiáveis e as chaves exigem um ponto-e-vírgula antes do final, enquanto os parênteses não. A sintaxe na qual estou me decidindo tenta eliminar o ponto-e-vírgula e usar o "& &" formulário:

[$ USER == 'x'] || {echo "Time to bail" & & saída 1; }

Portanto, em suma, os parênteses são mais agradáveis de se olhar do que os curlies, e os curlies com o requisito de ponto-e-vírgula fazem com que o alinhador pareça menos com um de uma linha.

    
por 21.10.2015 / 08:22