# 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" ]]
> # 好多了 -- 把逻辑判断分散到多个组之中
> ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://linuxstory.gitbook.io/advanced-bash-scripting-guide-in-chinese/zheng-wen/part2/08_operations_and_related_topics/08_4_operator_precedence.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
