6.5 shell算术
在以下情况中,shell可以计算算术表达式:shell扩展,或者使用 let 和带 -i 选项的 declare 内建命令。
计算结果是固定宽度的整数,且不做溢出检查,因此被0除会落入陷阱,并被标识为错误。操作符和他们的优先顺序,结合性,以及值和C语言一样。下面的操作符列表,以相同的优先级分组。优先级别按照降序排列。
id++ id--
变量用后增加,和用后减少
++id --id
变量用前增加,和用前减少
- +
一元减法和加法
! ~
逻辑非和按位非
**
幂运算
* / %
乘法,除法,取余
+ -
加法,减法
<< >>
按位左移,按位右移
<= >= < >
比较
== !=
等于和不等于
&
按位与
^
按位异或
|
按位或
&&
逻辑与
||
逻辑或
expr ? expr : expr
条件操作符
= *= /= %= += -= <<= >>= &= ^= |=
赋值
expr1, expr2
逗号
shell变量可作为操作数,计算表达式之前进行参数扩展。在表达式内部,shell变量也可以用名字引用,而不使用参数扩展语法。一个为空或者未设置的shell变量,用名字引用而不使用参数扩展语法时,被当作0参与运算。变量被引用时,它的值被当作算术表达式参与运算,或者,变量使用了 'declare -i' 命令获得了整型属性,并赋予值。空当作0参与计算。在表达式中,shell变量不需要打开整型属性。
以0开头的常数被当作8进制数。以‘0x’ 或 '0X'开头的被当作16进制数。此外,[base#]n 形式的数字,其中base是可选的10进制数,它的值介于2和64之间,代表该数的进制, 而 n 是在该进制下的数。如果忽略了 base# ,则base是10。大于9的数字,按顺序用小写字母,大写字母,‘@’, 和 ‘_’ 表示。如果 base 小于等于36,交替使用小写字母和大写字母表示介于10和35之间的数。
操作符按照优先顺序计算。括号中的子表达式优先计算,而覆盖上述的优先顺序规则。
6.6 别名
别名可以使一个字符串代替一个单词,而该单词是一个简单命令的第一个单词。shell维护一个别名列表,这些别名使用内建命令 alias 和 unalias 设置和取消设置。
每一个简单命令的第一个单词,如果不被引号包括,将被检查是否是一个别名。如果是别名,该单词被别名的文本替换。字符 ‘/’, ‘$’, ‘`’, ‘=’ 和shell元字符或者被引号包括的上述字符,不能作为别名。替换的文本可以包含任何有效的shell输入,包括shell元字符。替换的文本的第一个单词要检查看是否是别名,但是如果该单词和正在扩展的别名相同,则不再次扩展。即,可以使用 ls 作为 "ls -F" 的别名,Bash不会迭代地扩展替换文本。如果别名值的最后的字符是空格或者tab字符,则紧跟在别名后面的命令单词也要检查别名扩展。
使用 alias 命令创建和列出别名,使用 unalias 命令移除。
就像在csh中那样,没有在替换文本中使用参数的机制。如果需要参数,必须要使用shell函数。(见 shell函数 章节)
shell不是交互式的时候,不做别名扩展,除非使用shopt命令设置了shell选项 expand_aliases 。(见 shopt内建命令 章节)
别名的定义和使用的规则有些容易混淆。Bash总是读取至少一个整行的输入后,才执行该行上的任何命令。别名是在读取命令时扩展,而不是在执行时扩展。此外,在同一行上出现的对另一个命令的别名定义,要在读取下一行输入时才生效。在别名定义同一行的后续命令,不受新别名的影响。当执行函数时,这种行为是个问题。当读入一个函数时,别名被扩展,而不是在函数执行时扩展,因为函数定义本身是一个复合命令。总之函数里的别名定义,直到该函数执行时才可用。为安全起见,总是把别名定义放在单独的行上,并且不在复合命令中使用 alias 。
从任何角度来说,shell函数都优于别名。