# 33.2. Operator Precedence

In a script, operations execute in order of precedence: the higher precedence operations execute before the lower precedence ones. [1]

Table 33-1. Operator Precedence

OperatorMeaningComments
HIGHEST PRECEDENCE
var++ var--post-increment, post-decrementC-style operators
++var --varpre-increment, pre-decrement

! ~negationlogical / bitwise, inverts sense of following operator

**exponentiationarithmetic operation
* / %multiplication, division, moduloarithmetic operation
+ -addition, subtractionarithmetic operation

<< >>left, right shiftbitwise

-z -nunary comparisonstring is/is-not null
-e -f -t -x, etc.unary comparisonfiles
< -lt > -gt <= -le >= -gecompound comparisonstring and integer
-nt -ot -efcompound comparisonfiles
== -eq != -neequality / inequalitytest operators, string and integer

&ANDbitwise
XORexclusive OR, bitwise
|ORbitwise

&& -aANDlogical, compound comparison
|| -oORlogical, compound comparison

?:trinary operatorC-style
=assignment(do not confuse with equality test)
*= /= %= += -= <<= >>= &= !=combination assignmenttimes-equal, divide-equal, mod-equal, etc.

,commalinks a sequence of operations
LOWEST PRECEDENCE

In practice, all you really need to remember is the following:

• The "My Dear Aunt Sally" mantra (multiply, divide, add, subtract) for the familiar arithmetic operations.

• The compound logical operators, &&, ||, -a, and -o have low precedence.

• The order of evaluation of equal-precedence operators is usually left-to-right.

Now, let's utilize our knowledge of operator precedence to analyze a couple of lines from the /etc/init.d/functions file, as found in the Fedora Core Linux distro.

 ``` 1 while [ -n "\$remaining" -a "\$retry" -gt 0 ]; do 2  3 # This looks rather daunting at first glance. 4  5  6 # Separate the conditions: 7 while [ -n "\$remaining" -a "\$retry" -gt 0 ]; do 8 # --condition 1-- --condition 2- 9  10 # If variable "\$remaining" is not zero length 11 #+ AND (-a) 12 #+ variable "\$retry" is greater-than zero 13 #+ then 14 #+ the [ expresion-within-condition-brackets ] returns success (0) 15 #+ and the while-loop executes an iteration. 16 # ============================================================== 17 # Evaluate "condition 1" and "condition 2" ***before*** 18 #+ ANDing them. Why? Because the AND (-a) has a lower precedence 19 #+ than the -n and -gt operators, 20 #+ and therefore gets evaluated *last*. 21  22 ################################################################# 23  24 if [ -f /etc/sysconfig/i18n -a -z "\${NOLOCALE:-}" ] ; then 25  26  27 # Again, separate the conditions: 28 if [ -f /etc/sysconfig/i18n -a -z "\${NOLOCALE:-}" ] ; then 29 # --condition 1--------- --condition 2----- 30  31 # If file "/etc/sysconfig/i18n" exists 32 #+ AND (-a) 33 #+ variable \$NOLOCALE is zero length 34 #+ then 35 #+ the [ test-expresion-within-condition-brackets ] returns success (0) 36 #+ and the commands following execute. 37 # 38 # As before, the AND (-a) gets evaluated *last* 39 #+ because it has the lowest precedence of the operators within 40 #+ the test brackets. 41 # ============================================================== 42 # Note: 43 # \${NOLOCALE:-} is a parameter expansion that seems redundant. 44 # But, if \$NOLOCALE has not been declared, it gets set to *null*, 45 #+ in effect declaring it. 46 # This makes a difference in some contexts.```

To avoid confusion or error in a complex sequence of test operators, break up the sequence into bracketed sections.
 ``` 1 if [ "\$v1" -gt "\$v2" -o "\$v1" -lt "\$v2" -a -e "\$filename" ] 2 # Unclear what's going on here... 3  4 if [[ "\$v1" -gt "\$v2" ]] || [[ "\$v1" -lt "\$v2" ]] && [[ -e "\$filename" ]] 5 # Much better -- the condition tests are grouped in logical sections.```

### Notes

 [1] Precedence, in this context, has approximately the same meaning as priority