运算操作
shell脚本在各种linux操作系统中触手可及,利用它执行特定任务十分强大且便捷,通用性强,反而是在处理各种看似简单的四则运算等操作上让人眉头一皱,整理记录shell中的运算类操作如下。
四则运算
不经常写脚本的同学,遇到的第一个坎就是这个——shell脚本中不能直接做加减乘除(报错command not found
):
可以在线Shell工具尝试undefinedBash 在线工具 | 菜鸟工具。
#!/bin/bash
echo '加法错误示范'
1+1
# 执行结果
加法错误示范
script.sh: line 3: 1+1: command not found
Exited with error status 127
它把1+1
当做一条命令去解析,自然找不到。正确写法,举常用的两种:
- 双括号包括
- expr表达式运算
#!/bin/bash
echo '双括号(())--此处不用空格'
((a=1+1))
echo $a
#!/bin/bash
echo 'expr 必须带空格'
expr 1 + 1
运行结果:
双括号(())--此处不用空格
2
expr 必须带空格
2
逻辑运算
这里只说3种逻辑运算符:与(AND),或(OR),非(NOT):
在shell中,”与”的运算符为”-a”,”与”的逻辑运算符也可以用”&&”表示。
在shell中,”或”的运算符为”-o”,”或”的逻辑运算符也可以用”||”表示。
- !(非) &&(与) ||(或)中“!”优先级最高。
- 逻辑运算符中的“&&”和“||”低于关系运算符,“!”高于算术运算符。
#!/bin/bash
a=1
b=98
((c=$a+$b))
if [ $a > 0 ] && [ $b > 0 ]
then
echo "两个正数"
fi
if [ $c -ne 100 ];then echo "没有满分";fi
运行结果:
两个正数
没有满分
逻辑组合更多细节参考:shell中的逻辑运算/布尔运算/短路与/短路或-博客
更多逻辑比较的写法,如-f 判断文件是否存在,-d判断目录是否存在,可参考Linux shell 逻辑运算符、逻辑表达式详解
使用场景:if条件的组合
列表求和
前面已经解决了基础的加减乘除运算的问题,有一个更常见的需求是要把获取到的数值进行求和:
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
let sum=sum+$i
let i+=1
done
echo $sum
# 结果是5050(当然啦,高斯会告诉你更快的算法)
使用场景:一般是配合从文件中匹配检索到特定的数值(grep+awk),然后进行循环求和
小Case集合
1. shell脚本参数表示(最基础)
写法 | 含义 |
---|---|
$# | 指的是参数个数 |
$0 | 指的是脚本本身的名字,如终端输入./foo_config. sh hello world ,$0值就是xxxx_config. sh |
$1 | 指的是传递给该shell脚本的第一个参数,$1值就是hello |
$2 | 指的是传递给该shell脚本的第二个参数,$2值就是world |
$$ | 指的是脚本运行的当前进程ID号 |
$? | 指的是显示最后命令的退出状态,0表示没有错误,其他表示有错误 |
基本功:使用#判断脚本参数、函数参数是否为空,使用?判断最后命令执行是否成功进行相应操作,如错误重试,错误提示。
#!/bin/bash
function getNumber(){
echo $#
}
getNumber who am i
echo $?
# 结果是3和0
2. curl只获取http响应码
当你需要对某个请求的成功与否做处理时你就需要本知识。
curl -s -w "%{http_code}" 'your_http_url' -o /dev/null
# 用http_code来判断请求的响应情况,200,404等等
3. 实现try catch
{ } && { }
这种情况下,只有左边成功执行了,右边的shell才会执行。
{ } || { }
这种情况,左边shell脚本执行失败,右边才会执行,刚好可以实现try catch
的功能。
{ # try
command1
#save your output
} || {
# catch
# save log for exception
}
这只是利用了逻辑与或的原理达成此类效果。要注意的是这个写法需要在shell脚本中使用,不能直接在控制台执行,否则大括号也会被当做命令解析而报错。
常见错误处理
unary operator expected
xxx.sh: line 133: [: -eq: unary operator expected
# 例如第133行语句是 if [ $1 -eq 1 ],但调用时没有传参数值
这种错误在我们多次进行获多次调用变量比较时很容易遇到:作者在编写一个服务器环境处理脚本的时候,已一个变量来判断是用户主动调用还是被动使用,在被动使用时传递了变量0,主动调用时未传递,就有此报错。
原因:如果变量$1
值为空,语句就成了 [ -eq 1 ]
,显然 [
和 "1" 不相等并且缺少前面的 [
符号,所以报了这样的错误。当然不总是出错,如果$1
值不为空,语句就正常运行了,所以这样的错误是条件触发的比较隐蔽。
“unary operator expected”这个报错翻译过来是“期望一元运算符”,原意是说这里应该是一个一元操作符,如逻辑非,但并不是我们程序的本意。
解决办法(任选其一):
a. 保证传参$1
不为空,赋予其默认值即可。
b. 将语句改写为if [[ $1 -eq 1 ]]
a方案是逻辑层面的规避,要求自检代码,保证没有空值比较,类似于java等的非null判定
b方案是语法层面规避
syntax error: unexpected end of file
一般是少写了done
或者fi
,分别用于do
和if
的配对结束。
错误写法:
#!/bin/bash
a=1
b=98
((c=$a+$b))
if [ $a > 0 ] && [ $b > 0 ]
then
echo "两个正数"
## 错误示范,请勿模仿!
报错:
script.sh: line 8: syntax error: unexpected end of file
Exited with error status 2
line x: [: missing `]'
常见于if
语句中由于缺少空格而导致的错误。if
后面的方括号表达式前后记得加空格。
line x: [: too many arguments
#!/bin/bash
foo="hello world"
if [ $foo = "hi" ]
then
echo "打招呼"
fi
运行结果是:script.sh: line 3: [: too many arguments
。
当$foo
包含空格时,就出现上述的错误了,应当用双引号将变量括起来。
#!/bin/bash
foo="hello world"
if [ "$foo" = "hi" ]
then
echo "打招呼"
else
echo "其他"
fi
变量赋值时等号两侧不能加空格
#!/bin/bash
a=5
b = 5
if [ $a = $b ]
then
echo "a和b相等"
fi
运行结果:
script.sh: line 3: b: command not found
script.sh: line 4: [: 5: unary operator expected