Shell脚本中的几种计算方式
expr
这是我常用的一个命令,它不仅可以实现数值运算,还可以进行数值或字符串的比较,字符串的匹配、提取、统计长度,甚至可以判断变量或参数是否为整数、是否为空、是否为0等。
-
处理算术表达式
- expr命令可以处理普通的算术操作,但是只能是整数1,并且算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
- +、-、*、/、%,操作符的两边都要用空格隔开。并且需要注意一些特殊的字符,例如
*、/、()等等。这些字符在shell中有特殊含义,需要使用 \ 进行转义或者 ‘’ 包围。 - 例子
- 直接返回计算结果

- 使用变量进行计算,同时对 * 进行了转义

- 未进行转义的情况

- 对非整数进行处理的情况

- 直接返回计算结果
-
处理字符串表达式
-
字符串表达式的优先级高于数值表达式和逻辑关系表达式
-
模式匹配
-
expr STRING : REGEX等价于expr match STRING REGEX -
两个参数都会被视为字符格式,第二个参数会被作为正则表达式解释,并且它默认隐含前缀 ^ 。
-
如果匹配成功,且REGEX使用了’\(‘和’\)’2,则此表达式返回匹配到的。
注:只有第一个’\(…\)‘会引用返回的值;其余的’\(…\)'只在正则表达式分组时有意义。 -
如果未使用’\(‘和’\)’,则返回匹配的字符数。

-
如果匹配失败,如果REGEX中使用了’\(‘和’\)’,则此表达式返回空字符串,否则返回为0。

-
-
返回字符串子串
expr substr STRING POSITION LENGTH- 返回STRING字符串中从POSITION开始,长度最大为LENGTH的字符串子串。如果POSITION或LENGTH为负数、0或非数值,则返回空字符串。3

-
子字符串中任意字符在字符串中的最前一个位置
expr index STRING CHARSET- CHARSET中任意单个字符在STRING中最前面的字符位置。如果在STRING中完全不存在CHARSET中的字符,则返回0。4

-
返回字符串长度
expr length STRING- 返回STRING的字符数

-
处理关键字
+ TOKEN- 将字符串TOKEN解析为普通字符串,即使TOKEN是像match或操作符"/"一样的关键字。

-
-
逻辑表达式
expr支持普通的逻辑连接和逻辑关系,但是它的优先级最低。
| 表达式 | 含义 |
|---|---|
| ARG1 | ARG2 | 如果ARG1非0,则返回ARG1的值,否则返回ARG2。 |
| 但如果任意一个参数为空,则报错,除非空字符串使用引号包围 | |
| ARG1 & ARG2 | 如果两个参数都非0,则返回ARG1,否则返回0。 |
| 但任意一个参数为空,则报错,除非空字符串使用引号包围 | |
| ARG1 < ARG2 | ARG1 小于ARG2 |
| ARG1 <= ARG2 | ARG1 小于或等于ARG2 |
| ARG1 = ARG2 | ARG1 等于ARG2 |
| ARG1 != ARG2 | ARG1 不等于ARG2 |
| ARG1 >= ARG2 | ARG1 大于或等于ARG2 |
| ARG1 > ARG2 | ARG1 大于ARG2 |
注: |和& 在使用中都需要转义,或者用 ‘’ 括起来
对于某个参数是空的情况
注:除了 |和& ,其余的逻辑符号在表达式为真时,返回1,否则返回0.这与程序返回值对比看有点别扭。

我们依旧不能忘记特殊字符的转义,下面的 > 被解析成了输出重定向

$[ operation ]
$[]符号的方便之处在于它对方括号内的空格无太严格的要求,同时方括号内的运算符不需要进行转义,但是它依旧只能处理整数运算。


let
let命令属于内建命令,执行它的开销要少于上面两种,并且还提供了求幂运算符**、自加自减等。
let arg [arg ...] #arg代表运算式
使用let命令时需要注意一些细节:
- let表达式内变量不用加$

- 运算符两边不可以有空格,有的话就必须用单引号或者双引号括起来

- let后面必须是赋值表达式,即为变量赋值
与expr等命令不同,expr 3 + 2将返回5,而形如let 3+2是没有意义的。

- 求幂示例

- 自增示例

使用双括号
(())也属于内建命令,并且依然只支持整型计算,双括号内的运算符不需要进行转义。
- 它的命令格式形如 ((expression)), 其中 expression 可以是任意的比较或者赋值表达式5。

- ((expression)) ,如果表达式的结果为0,那么返回的退出状态码为1,而一个非零值的表达式所返回的退出状态码将为0。

- ((expression)) 若用于自增自减等常用的算术运算时,与let命令类似

- ((expression)) 常用来计算并测试算术表达式,搭配c风格的for,while,if等


bash内建计算器
bc命令作为 一个任意精度的计算器语言 ,它可以补充浮点数计算的能力,bc甚至可以称得上是一种编程语言了,它支持变量、数组、输入输出、分支结构、循环结构、函数等基本的编程元素,当然它的开销相对于上面那些来说也是最大的。在shell脚本中我们一般通过管道和输入重定向来使用 bc,而在命令行环境中,我们直接输入bc即可进入交互式的数学计算。
下面是bc命令的一些常用选项:
| 选项 | 说明 |
|---|---|
| -h | --help | 显示帮助信息 |
| -v | --version | 显示版本信息 |
| -l | --mathlib | 使用标准数学库 |
| -i | --interactive | 强制交互 |
| -w | --warn | 显示 POSIX 的警告信息 |
| -s | --standard | 使用 POSIX 标准来处理 |
| -q | --quiet | 不显示欢迎信息 |
- 交互式使用示例
图中前四行是版本及版权信息,使用-q选项可以不输出,接下来我们便可以像使用计算器一样输入计算式,计算结果会在下一行输出,接下来输入quit退出程序

bc中可以使用变量,并且自定义函数
bc的四个内置变量
| 变量名 | 说明 |
|---|---|
| scale | 指定精度,也即小数点后的位数;默认为 0,也即不使用小数部分 |
| ibase | 指定输入的数字的进制,默认为十进制 |
| obase | 指定输出的数字的进制,默认为十进制 |
| last或者. | 表示最近打印的数字 |

scale默认为0,当指定大于0的值时,就可以输出小数点后面的位了
八进制的144即十进制的100,八进制的10即十进制的8,.即重复输出最后的数字
- 内置函数
&esmp;bc命令还有一些内置函数,要想使用这些内置函数,在输入 bc 命令时需要使用-l选项启用数学库
| 函数名 | 说明 |
|---|---|
| s(var) | 计算var的正弦值,var是弧度值 |
| c(var) | 计算var的余弦值,var是弧度值 |
| a(var) | 计算var的反正切值,返回弧度值 |
| l(var) | 计算var的自然对数 |
| e(var) | 求 e 的var次方 |
| j(n, m) | 贝塞尔函数,计算从 n 到m的阶数 |
在一行内的多个表达式需要用;隔开
-
shell脚本中使用
bc一般会借助管道命令或者输入重定向-
借助管道命令
类似于:echo "expression" | bc将单个或多个表达式通过管道命令传给
bc可以直接输出计算结果。

同时也可以将计算结果赋值给变量:var=$(echo "expression" | bc)
利用shell中的变量进行计算:

或者调用它的内置变量

-
借助输入重定向
类似于:
bc << EOF expressions EOF -
当有多个表达式时,这样书写比较方便清晰。
1671

被折叠的 条评论
为什么被折叠?



