Bash's conditional operator and assignment
Solution 1
Bash parses your last command as
a=1; (( (a? b=1 : c)=1 ))
which should make clear why it does not work. Instead you have to use
a=1; (( a? b=1 : (c=1) ))
Solution 2
This is called a ternary assignment
expression. Here's a bit from another answer of mine:
% 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
You see, as you say, this is a conditional assignment operation. It depends upon conditions. The syntax works like this:
$((var = $condition <compare_operator> $condition \
?if $true_assign :or $false_assign ))
I don't believe you are using this correctly.
From wikipedia:
?:
is used as follows:
condition ? value_if_true : value_if_false
The condition is evaluated true or false as a Boolean expression. On the basis of the evaluation of the Boolean condition, the entire expression returns value_if_true if condition is true, but value_if_false otherwise. Usually the two sub-expressions value_if_true and value_if_false must have the same type, which determines the type of the whole expression. The importance of this type-checking lies in the operator's most common use—in conditional assignment statements. In this usage it appears as an expression on the right side of an assignment statement, as follows:
variable = condition ? value_if_true : value_if_false
The
?:
operator is similar to the way conditional expressions (if-then-else
constructs) work in functional programming languages, like Scheme, ML, and Haskell, since if-then-else forms an expression instead of a statement in those languages.
I think your specific problem is related to this:
As in the if-else construct only one of the expressions 'x' and 'y' are evaluated.
If you read through the above link on ternary
expressions you'll see that evaluation is short-circuited so your assignment on the false side errors because 1 = true
.
In any case, it doesn't matter too much because I don't think this does what you think it does.
Solution 3
Ternary operators return a value based on a test. They are not used for branching.
Here's one way to get a pseudo-ternary operator for bash (note the 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
Related videos on Youtube
MS.Kim
Updated on September 18, 2022Comments
-
MS.Kim almost 2 years
Can we use bash's conditional operator with assignment operators after colon?
Bash reference manual explains the arithmetic operators as follows.
- conditional operator
expr ? expr : expr
- assignment
= *= /= %= += -= <<= >>= &= ^= |=
First, this code seems to work well:
a=1; ((a? b=1 : 2 )) #seems to work
But when I use assignment operators after
:
, I got 'attempted assignment to non-variable' error:a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Why can we use only assignment operators before colon?
-
Admin about 10 years@devnull I think the code's readability depends most upon who reads it. Still, it may be true what you say, but I've tested
ternary
operators indash, zsh, sh
, andbash
and they all behave the same, despite their not being specified by POSIX. Your example only works inbash
andzsh
as far as I know. However, this is POSIX friendly:( : ${a?} ) && b=1 || c=1
. I also find it far easier to read than eitherternary
or your own example.
- conditional operator