> For the complete documentation index, see [llms.txt](https://linuxstory.gitbook.io/advanced-bash-scripting-guide-in-chinese/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://linuxstory.gitbook.io/advanced-bash-scripting-guide-in-chinese/zheng-wen/part2/08_operations_and_related_topics/08_4_operator_precedence.md).

# 8.4 运算符优先级

在脚本中，运算执行的顺序被称为*优先级*: 高优先级的操作会比低优先级的操作先执行。

**表 8-1. 运算符优先级(从高到低)**

| 运算符                        | 含义           | 注解                  |
| -------------------------- | ------------ | ------------------- |
| var++ var--                | 后缀自增/自减      | C风格运算符              |
| ++var --var                | 前缀自增/自减      |                     |
|                            |              |                     |
| ! \~                       | 按位取反/逻辑取反    | 对每一比特位取反/对逻辑判断的结果取反 |
|                            |              |                     |
| \*\*                       | 幂运算          | 算数运算符               |
| \* / %                     | 乘, 除, 取余     | 算数运算符               |
| + -                        | 加, 减         | 算数运算符               |
|                            |              |                     |
| << >>                      | 左移, 右移       | 比特位运算符              |
|                            |              |                     |
| -z -n                      | 一元比较         | 字符串是/否为空            |
| -e -f -t -x, etc           | 一元比较         | 文件测试                |
| -lt -gt -le -ge <= >=      | 复合比较         | 字符串/整数比较            |
| -nt -ot -ef                | 复合比较         | 文件测试                |
|                            |              |                     |
| &                          | AND(按位与)     | 按位与操作               |
| ^                          | XOR(按位异或)    | 按位异或操作              |
| \|                         | OR(按位或)      | 按位或操作               |
|                            |              |                     |
| && -a                      | AND(逻辑与)     | 逻辑与, 复合比较           |
| \|\| -o                    | OR(逻辑或)      | 逻辑或, 复合比较           |
|                            |              |                     |
| ? :                        | if/else三目运算符 | C风格运算符              |
| =                          | 赋值           | 不要与test中的等号混淆       |
| \*= /= %= += -= <<= >>= &= | 赋值运算         | 先运算后赋值              |
|                            |              |                     |
| ,                          | 逗号运算符        | 连接一系列语句             |

实际上，你只需要记住以下规则就可以了:

* 先乘除取余，后加减，与算数运算相似
* 复合逻辑运算符，&&, ||, -a, -o 优先级较低
* 优先级相同的操作按*从左至右*顺序求值

现在，让我们利用运算符优先级的知识来分析一下*Fedora Core Linux*中的`/etc/init.d/functions`文件。

```
while [ -n "$remaining" -a "$retry" -gt 0 ]; do

# 初看之下很恐怖...


# 分开来分析
while [ -n "$remaining" -a "$retry" -gt 0 ]; do
#       --condition 1-- ^^ --condition 2-

#  如果变量"$remaining" 长度不为0
#+      并且AND (-a)
#+ 变量 "$retry" 大于0
#+ 那么
#+ [ 方括号表达式 ] 返回成功(0)
#+ while-loop 开始迭代执行语句。
#  ==============================================================
#  "condition 1" 和 "condition 2" 在 AND之前执行，为什么？
#  因为AND(-a)优先级比-n,-gt来得低，逻辑与会在最后求值。
#################################################################

if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" ] ; then


# 同样，分开来分析
if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" ] ; then
#    --condition 1--------- ^^ --condition 2-----

#  如果文件"/etc/sysconfig/i18n" 存在
#+      并且AND (-a)
#+ 变量 $NOLOCALE 长度不为0
#+ 那么
#+ [ 方括号表达式 ] 返回成功(0)
#+ 执行接下来的语句。
#
#  和之前的情况一样，逻辑与AND(-a)最后求值。
#  因为在方括号测试结构中，逻辑运算的优先级是最低的。
#  ==============================================================
#  注意:
#  ${NOLOCALE:-} 是一个参数扩展式，看起来有点多余。
#  但是, 如果 $NOLOCALE 没有提前声明, 它会被设成null，
#  在某些情况下，这会有点问题。
```

> ![tip](http://tldp.org/LDP/abs/images/tip.gif)为了避免在复杂比较运算中的错误，可以把运算分散到几个括号结构中。
>
> ```
> if [ "$v1" -gt "$v2"  -o  "$v1" -lt "$v2"  -a  -e "$filename" ]
> # 这样写不清晰...
>
> if [[ "$v1" -gt "$v2" ]] || [[ "$v1" -lt "$v2" ]] && [[ -e "$filename" ]]
> # 好多了 -- 把逻辑判断分散到多个组之中
> ```
