true && echo foo
vai imprimirfoo
.false && echo foo
não imprimiráfoo
.bash -c "exit $a" && echo foo
será impressofoo
dependendo de$a
.
Existe uma maneira mais elegante de escrever o último? Parece um pouco demais ter que iniciar um shell simplesmente para definir o valor de saída. Estou pensando em algo como:
return $a && echo foo
exit $a && echo foo
exceto return
funciona apenas em funções e exit
fará com que echo foo
nunca seja executado.
Elegante neste contexto significa:
- Fácil de entender
- Portátil
- Fácil de ler
- fácil de escrever
- Fácil de lembrar
- Curto
- Alta performance
Por exemplo, se true
pegasse o código de saída como um argumento (e este era um recurso documentado), seria muito elegante.
Então, existe uma maneira mais elegante?
Fundo
Um dos lugares que isso pode ser usado é para:
$ parallel 'setexitval {= $_%=3 =} || echo $?' ::: 0 1 2 3
A versão de Kusalananda é provavelmente a melhor. Está claro o que está acontecendo. Não é longo e complicado de escrever. É fácil de lembrar e portátil. A única desvantagem é que ele bifurca outro shell (custa ~ 0,5 ms):
$ parallel '(exit {= $_%=3 =}) || echo $?' ::: 0 1 2 3
Outra situação é quando você deseja simular uma condição de erro. Digamos, se você tiver um programa de execução longa, que define diferentes códigos de saída e estiver escrevendo algo que reagirá aos diferentes códigos de saída. Em vez de ter que executar o programa de execução longa, você pode usar (exit $a)
para simular a condição.
Bem,
return
funciona em uma função, então vamos fazer uma:Ele precisa de um pouco mais de configuração do que um subshell, mas é mais curto para usar depois disso e não requer a bifurcação de um subshell.
Use um subshell que sai com o valor especificado.
Isso produzirá
5
:Isso produzirá
foo
e0
(observe, esse zero é definido porecho
sucesso, não porexit
no subshell):Em sua forma abreviada (sem configurar visivelmente
a
ou investigar$?
explicitamente):Minha resposta é aquela que vem de apenas pegar a questão pelo valor de face e resolvê-la como um questionário curioso, "como podemos definir
$?
(usando notação útil)". Não tento buscar nenhum significado ou função mais profunda ou mesmo contexto neste caso (porque não foi dado). Além disso, não julgo a validade, eficiência ou usabilidade da solução. Às vezes, em minhas respostas, digo coisas como "... mas não faça isso, porque ...", seguido de "em vez disso, faça isso ...". Nesse caso, estou optando por interpretar a pergunta simplesmente como um questionário curioso.Mais antecedentes foram adicionados à pergunta.
Minha opinião sobre a questão de bifurcar um subshell é que scripts como o GNU
configure
fazem isso o tempo todo e que não é muito lento, a menos que seja feito em um loop realmente apertado (de longa duração).Não posso dizer muito sobre o uso disso no/com o GNU
parallel
, pois não sou um usuário frequente desse software.Uma opção (provavelmente mais rápida, mas não muito mais elegante):
Ele executa
echo
, mas não define o valor de saída como$a
, portanto, é uma solução medíocre.Vamos examinar suas suposições:
true && echo foo
imprimirá foo. Correto porque&&
adere a AND com lógica de curto-circuito; devido à associatividade à esquerda nos operadores&&
e||
se o comando mais à esquerda retornar o status de saída com sucesso 0 (o quetrue
sempre ocorre), o comando mais à direita para esse operador será executado.false && echo foo
não imprimirá foo. Exatamente o caso oposto do explicado acima.bash -c "exit $a" && echo foo
imprimirá foo dependendo de$a
. Suposição essencialmente errada que$a
controla&&
. Por&&
ser lógica AND, ele reconhece apenas dois estados - sucesso ou falha, onde falha é qualquer status de saída acima de 0. Assimexit 1
, eexit 2
eexit 3
- todos são irrelevantes para&&
; falha é falha independentemente do$a
valor; é por issoecho foo
que não funciona.Portanto, a resposta é não, não há maneira mais elegante de fazer algo que opere sob suposições erradas de qualquer maneira. No entanto, se o seu objetivo é definir o status de saída por meio do comando, basta usar o que a resposta de Kusalananda sugere - um subshell. Pessoalmente, não vejo nada diferente da
bash -c
parte, exceto que o subshell pode ser implementado como processo filho/processo bifurcado em vez de processo separado; ainda não é o ideal. Observe que$?
também não deve ser definido pelo usuário por meio de variável - destina-se a comandos para comunicar sucesso ou falha.Vamos mudar o foco
$a
por um segundo. Por que definir$?
eecho foo
, se você pode verificar diretamente$a
? Não faz sentido colocar o$a
valor onde ele não pertence de qualquer maneira, ou seja, em$?
. Eu recomendaria mudar o foco de "elegante" (o que quer que isso signifique) para "lógico" e "funcional".Tudo bem, mas vamos jogar o seu jogo. Tomando uma modesta inspiração da resposta de ilkkachu . Essa abordagem, no entanto, remove a necessidade de forçar a execução condicional de eco. Irá ecoar apenas se uma variável fornecida indicar sucesso e
return
impedir sua execução.O que pode não ser óbvio é que você pode fazer
thing $a