¿Podemos usar el operador condicional de bash con operadores de asignación después de dos puntos?
Bash Reference Manual explica los operadores aritméticos de la siguiente manera.
- operador condicional
expr ? expr : expr
- asignación
= *= /= %= += -= <<= >>= &= ^= |=
Primero, este código parece funcionar bien:
a=1; ((a? b=1 : 2 )) #seems to work
Pero cuando uso operadores de asignación después de :
, aparece el error «intento de asignación a no variable»:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
¿Por qué podemos usar solo operadores de asignación antes de los dos puntos?
Comentarios
Respuesta
Bash analiza su último comando como
a=1; (( (a? b=1 : c)=1 ))
lo que debería aclarar por qué no funciona. En su lugar, debe utilizar
a=1; (( a? b=1 : (c=1) ))
Respuesta
Esto se llama ternary assignment
expresión. Aquí «un poco de otra respuesta mía:
% 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
Como ves, como dices, esta es una operación de asignación condicional . Depende de las condiciones. La sintaxis funciona así:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
No creo que esté usando esto correctamente.
De wikipedia :
?:
se utiliza de la siguiente manera:
condition ? value_if_true : value_if_false
La condición se evalúa como verdadera o falsa como una expresión booleana. Sobre la base de la evaluación de la condición booleana, la expresión completa devuelve valor_si_verdadero si la condición es verdadera, pero valor_si_falso en caso contrario. Por lo general, las dos subexpresiones value_if_true y value_if_false deben tener el mismo tipo, lo que determina el tipo de toda la expresión. La importancia de esta verificación de tipos radica en el uso más común del operador: en declaraciones de asignación condicional. En este uso, aparece como una expresión en el lado derecho de una declaración de asignación, como sigue:
variable = condition ? value_if_true : value_if_false
El
?:
operador es similar a la forma en que las expresiones condicionales (if-then-else
construcciones) funcionan en lenguajes de programación funcionales, como Scheme, ML y Haskell, ya que if-then-else forma un expresión en lugar de una declaración en esos idiomas.
Creo que su problema específico está relacionado con esto:
Como en la construcción if-else, solo se evalúa una de las expresiones «x» e «y».
Si lee el enlace anterior sobre ternary
expresiones verás esa evaluación n está cortocircuitado por lo que su asignación en el lado falso errores porque 1 = true
.
En cualquier caso, no importa demasiado porque no creo que esto haga lo que crees que hace.
Respuesta
Los operadores ternarios devuelven un valor basado en una prueba. No se utilizan para ramificar.
Aquí hay una forma de obtener un operador pseudo-ternario para bash (tenga en cuenta las marcas de retroceso):
$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 endash, zsh, sh
ybash
y todos se comportan de la misma manera, a pesar de que POSIX no los especifica. Su ejemplo solo funciona enbash
yzsh
hasta donde yo sé. Sin embargo, esto es compatible con POSIX:( : ${a?} ) && b=1 || c=1
. También lo encuentro mucho más fácil de leer queternary
o su propio ejemplo.