Podemos usar o operador condicional do bash com operadores de atribuição após dois pontos?
O manual de referência do Bash explica os operadores aritméticos da seguinte maneira.
- operador condicional
expr ? expr : expr
- atribuição
= *= /= %= += -= <<= >>= &= ^= |=
Primeiro, este código parece funcionar bem:
a=1; ((a? b=1 : 2 )) #seems to work
Mas quando eu uso operadores de atribuição após :
, recebo o erro “tentativa de atribuição para não variável”:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Por que podemos usar apenas operadores de atribuição antes de dois pontos?
Comentários
Resposta
O Bash analisa seu último comando como
a=1; (( (a? b=1 : c)=1 ))
o que deve deixar claro por que ele não funciona. Em vez disso, você deve usar
a=1; (( a? b=1 : (c=1) ))
Resposta
Isso é chamado de ternary assignment
expressão. Aqui está um trecho de outra resposta minha:
% a=abc % b=abcd % t=10 ; f=5 % echo $((r=${#a}>${#b}?t:f)) ; echo $r > 5 > 5 % echo $((r=${#a}<${#b}?t:f)) ; echo $r > 10 > 10
Veja, como você disse, esta é uma operação de atribuição condicional . Depende das condições. A sintaxe funciona assim:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
Não acredito que você esteja usando isso corretamente.
De wikipedia :
?:
é usado da seguinte forma:
condition ? value_if_true : value_if_false
A condição é avaliada como verdadeira ou falsa como uma expressão booleana. Com base na avaliação da condição booleana, a expressão inteira retorna valor_se_verdadeira se a condição for verdadeira, mas valor_se_falso caso contrário. Normalmente, as duas subexpressões value_if_true e value_if_false devem ter o mesmo tipo, o que determina o tipo de toda a expressão. A importância dessa verificação de tipo reside no uso mais comum do operador – em instruções de atribuição condicional. Nesse uso, ela aparece como uma expressão no lado direito de uma instrução de atribuição, como segue:
variable = condition ? value_if_true : value_if_false
O
?:
operador é semelhante à maneira como as expressões condicionais (if-then-else
construções) funcionam em linguagens de programação funcionais, como Scheme, ML e Haskell, uma vez que if-then-else forma um expressão em vez de uma declaração nessas línguas.
Acho que seu problema específico está relacionado a este:
Como na construção if-else, apenas uma das expressões “x” e “y” são avaliadas.
Se você ler o link acima nas expressões ternary
você verá essa avaliação n está em curto-circuito, portanto, sua atribuição nos erros secundários false porque 1 = true
.
Em qualquer caso, não importa demais porque não acho que isso faça o que você pensa que faz.
Resposta
Operadores ternários retornam um valor com base em um teste. Eles não são usados para ramificação.
Esta é uma maneira de obter um operador pseudo-ternário para bash (observe os back-ticks):
$result=`[ < condition > ] && echo "true-result" || echo "false-result" `
$ a=
$ c=`[ $a ] && echo 1 || echo 0`
$ echo $c
0
$ a=5
$ c=`[ $a ] && echo 1 || echo 0`
$ echo $c
1
((a)) && b=1 || c=1
ternary
operadores emdash, zsh, sh
ebash
e todos se comportam da mesma forma, apesar de não serem especificados por POSIX. Seu exemplo só funciona embash
ezsh
até onde eu sei. No entanto, isso é compatível com POSIX:( : ${a?} ) && b=1 || c=1
. Também acho muito mais fácil de ler do queternary
ou seu próprio exemplo.