1. 数学运算
对任何编程语言都很重要的特性是操作数字的能力。遗憾的是,对shell脚本来说,这个处理过程会比较麻烦。在shell脚本中有两种途径来进行数学运算。
2. expr 命令
最开始,Bourne shell提供了一个特别的命令用来处理数学表达式。 expr 命令允许在命令行上处理数学表达式,但是使用很不方便。
owon@mark MINGW64 /c/Users/lyj/Desktop
$ expr 1 + 5
6
2.1 expr 命令操作符
操作符 描 述
-------------------------+---------------------------------------------------------------------
ARG1 | ARG2 | 如果 ARG1 既不是null也不是零值,返回 ARG1 ;否则返回 ARG2
ARG1 & ARG2 | 如果没有参数是null或零值,返回 ARG1 ;否则返回 0
ARG1 < ARG2 | 如果 ARG1 小于 ARG2 ,返回 1 ;否则返回 0
ARG1 <= ARG2 | 如果 ARG1 小于或等于 ARG2 ,返回 1 ;否则返回 0
ARG1 = ARG2 | 如果 ARG1 等于 ARG2 ,返回 1 ;否则返回 0
ARG1 != ARG2 | 如果 ARG1 不等于 ARG2 ,返回 1 ;否则返回 0
ARG1 >= ARG2 | 如果 ARG1 大于或等于 ARG2 ,返回 1 ;否则返回 0
ARG1 > ARG2 | 如果 ARG1 大于 ARG2 ,返回 1 ;否则返回 0
ARG1 + ARG2 | 返回 ARG1 和 ARG2 的算术运算和
ARG1 - ARG2 | 返回 ARG1 和 ARG2 的算术运算差
ARG1 * ARG2 | 返回 ARG1 和 ARG2 的算术乘积
ARG1 / ARG2 | 返回 ARG1 被 ARG2 除的算术商
ARG1 % ARG2 | 返回 ARG1 被 ARG2 除的算术余数
STRING : REGEXP | 如果 REGEXP 匹配到了 STRING 中的某个模式,返回该模式匹配
match STRING REGEXP | 如果 REGEXP 匹配到了 STRING 中的某个模式,返回该模式匹配
substr STRING POS LENGTH | 返回起始位置为 POS (从 1 开始计数)、长度为 LENGTH 个字符的子字符串
index STRING CHARS | 返回在 STRING 中找到 CHARS 字符串的位置;否则,返回 0
length STRING | 返回字符串 STRING 的数值长度
+ TOKEN | 将 TOKEN 解释成字符串,即使是个关键字
(EXPRESSION) | 返回 EXPRESSION 的值
-------------------------+--------------------------------------------------------------------
注意: 许多 expr 命令操作符在shell中另有含义(比如星号)。当它们出现在在 expr 命令中时,会得到一些诡异的结果。要解决这个问题,对于那些容易被shell错误解释的字符,在它们传入 expr 命令之前,需要使用shell的转义字符(反斜线)将其标出来。例如这样
$ expr 5 \* 2
2.2. 运算结果赋值变量
在shell脚本中使用 expr 命令很复杂,要将一个数学算式的结果赋给一个变量,需要使用命令替换来获取 expr 命令的输出。
var1=10
var2=20
var3=$(expr $var2 / $var1)
echo The result is $var3
The result is 2
3. 方括号命令
bash shell为了保持跟Bourne shell的兼容而包含了 expr 命令,但它同样也提供了一种更简单的方法来执行数学表达式。在bash中,在将一个数学运算结果赋给某个变量时,可以用美元符和方括号
$[ operation ]
将数学表达式围起来。
$ var1=$[1 + 5]
$ echo $var1
6
$ var2=$[$var1 * 2]
$ echo $var2
12
4. 浮点运算
我们首先来看下面的一个shell的除法运算,可以发现除法得到的小数部分被舍弃。
var1=100
var2=45
var3=$[$var1 / $var2]
echo The final result is $var3
2
bash shell数学运算符只支持整数运算。若要进行任何实际的数学计算,这是一个巨大的限制。有几种解决方案能够克服bash中数学运算的整数限制。最常见的方案是用内建的bash计算器,叫作 bc 。
4.1. bc 计算器的基本用法
bash计算器实际上是一种编程语言,它允许在命令行中输入浮点表达式,然后解释并计算该表达式,最后返回结果。bash计算器能够识别:
- 数字(整数和浮点数)
- 变量(简单变量和数组)
- 注释(以#或C语言中的 /* */ 开始的行)
- 表达式
- 编程语句(例如 if-then 语句)
- 函数
通过 bc 命令访问bash计算器:
$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'.
12 * 5.4
64.8
3.156 * (3 + 5)
25.248
quit # 要退出bash计算器,你必须输入 quit 。
$
内建变量 scale:
浮点运算是由内建变量 scale 控制的。scale 变量的默认值是 0,必须将这个值设置为你希望在计算结果中保留的小数位数,否则无法得到期望的结果。例如下面这样。
$ bc -q
3.44 / 5
0
scale=4
3.44 / 5
.6880
quit
4.2. 在脚本中使用 bc
现在你可能想问bash计算器是如何在shell脚本中帮助处理浮点运算的。可以用命令替换运行 bc 命令,并将输出赋给一个变量。基本格式如
variable=$(echo "options; expression" | bc)
。第一部分 options 允许你设置变量。如果你需要不止一个变量,可以用分号将其分开,例如下面这样。
var1=$(echo "scale=4; 3.44 / 5" | bc)
echo The answer is $var1
The answer is .6880
上面这个方法适用于较短的运算,但有时你会涉及更多的数字。如果需要进行大量运算,在一个命令行中列出多个表达式就会有点麻烦。比如下面的例子。
var1=20
var2=3.14159
var3=$(echo "scale=4; $var1 * $var1" | bc)
var4=$(echo "scale=4; $var3 * $var2" | bc)
echo The final result is $var4
有一个方法可以解决这个问题。 bc 命令能识别输入重定向,允许你将一个文件重定向到 bc命令来处理。但这同样会叫人头疼,因为你还得将表达式存放到文件中。最好的办法是使用内联输入重定向,它允许你直接在命令行中重定向数据。在shell脚本中,你可以将输出赋给一个变量。EOF 文本字符串标识了内联重定向数据的起止。记住,仍然需要命令替换符号将 bc 命令的输出赋给变量。
variable=$(bc << EOF
options
statements
expressions
EOF
)
使用方式:
var1=10.46
var2=43.67
var3=33.2
var4=71
var5=$(bc << EOF
scale = 4
a1 = ( $var1 * $var2)
b1 = ($var3 * $var4)
a1 + b1
EOF
)
echo The final answer for this mess is $var5
The final answer for this mess is 2813.9882