#创作灵感#
在Shell脚本中进行数字计算可以使用多种方式,这是shell基础笔记的进阶,里面会有一些练习脚本,尽量加上详细的注释方便阅读
1、常用数值计算符号对照表
只需记忆几个常用的即可,在使用中熟练是最好的方式
2、简单的数值计算
1.双小括号运算"(())"
示例如下
#三种不同的写法,括号内为2与(2的三次方)相加,然后减去(4除以3的余数)
#第一种,变量赋值在括号内进行
[root@bogon ~]# ((a=2+2**3-4%3))
[root@bogon ~]# echo $a
9
#第二种,变量赋值在括号外进行
[root@bogon ~]# b=$((2+2**3-4%3))
[root@bogon ~]# echo $b
9
#第三种,不使用变量,进行数值运算
[root@bogon ~]# echo $((2+2**3-4%3))
9
脚本练习:写一个两个数字加减乘除的运算脚本,示例如下:
read命令:用于读取用户输入,常见参数有
-p:设置提示信息
-t:设置等待用户输入超时时间,默认单位秒
#! /bin/bash
#先定义一个简单函数,用来输出报错信息和状态码
#运算最少有两个数字参与,通过函数可以少写一遍报错代码
error_report()
{
printf "请输入纯数字\n"
exit 1
}
#读取用户的输入
read -p "请输入第一个数字:" firstnum
#判断用户输入的是否为纯数字
#if [ -n ]后面如果不为空则条件成立,就会调用上方函数报错
if [ -n "`echo $firstnum | sed 's/[0-9]//g'`" ]
then
error_report
fi
#读取用户输入的运算符,这里把符号限制在,加减乘除
read -p "请输入您的运算符:" operator
#判断用户输入的是不是加减乘除
#这里报错只写一次所以不使用函数了
if [ -n "`echo $operator | sed 's/['+','-','*','/']//g'`" ]
then
echo "只允许输入+-*/"
exit 1
fi
#读取
read -p "请输入第个数字:" secondnum
#判断用户输入的是否为纯数字
#if [ -n ]后面如果不为空则条件成立,就会调用上方函数报错
if [ -n "`echo $secondnum | sed 's/[0-9]//g'`" ]
then
error_report
fi
echo "${firstnum}${operator}${secondnum}的结果是:$((${firstnum}${operator}${secondnum}))"
2.特殊运算字符++,--
此处需要注意的点为++a与a++的区别
++a:先计算a+1,然后将结果赋值给a
a++:先对a进行操作,再执行a+1,然后将结果赋值给a
[root@bogon ~]# a=5
[root@bogon ~]# echo $a
5
[root@bogon ~]# echo $((++a))
6
###############################分隔线###################################
[root@bogon ~]# a=5
[root@bogon ~]# echo $a
5
[root@bogon ~]# echo $((a++))
5
[root@bogon ~]# echo $a
6
3.let命令运算
let命令的执行,效果等同于双小括号,且双小括号为内置函数,效率更高
命令演示
[root@bogon ~]# a=5
[root@bogon ~]# a=a+5
[root@bogon ~]# echo $a
a+5
#########################################################################
[root@bogon ~]# a=5
[root@bogon ~]# a=$a+5
[root@bogon ~]# echo $a
5+5
#########################################################################
[root@bogon ~]# a=5
[root@bogon ~]# let a=a+5
[root@bogon ~]# echo $a
10
脚本练习:写一个检查网站存活状态的脚本
#!/bin/bash
checkurl()
{
timeout=5
fails=0
success=0
while true
do
wget --timeout=${timeout} --tries=1 http://192.168.189.142 -q -O /dev/null
#执行wget这条命令后,成功$?返回0否则返回1,下面-ne是不等于的意思
if [ $? -ne 0 ]
then
let fails=fails+1
else
let success=success+1
fi
#成功次数大于等于1时网站正常
if [ $success -ge 1 ]
then
echo “正常”
exit 0
fi
#失败次数大于等于2时异常
if [ ${fails} -ge 2 ]
then
#这里可以添加发送邮件告警的命令,这就不演示了
echo "异常"
exit 2
fi
done
}
checkurl
运行效果(左侧为nginx运行状态)
4.expr命令
一个简单的计算器,使用命令expr --help可以看到expr的各种用法,因其以空格作为格式传入参数,实际使用起来体验感并不好,具体使用情况如下:
[root@bogon ~]# expr 5+3
5+3
[root@bogon ~]# expr 5 +3
expr: 语法错误:未预期的参数 “+3”
——————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# expr 5 + 3
8
——————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# expr 5 * 3
expr: 语法错误:未预期的参数 “anaconda-ks.cfg”
#这里显示的未预期参数其实是*号在这里被解释成了通配符
[root@bogon ~]# ls
anaconda-ks.cfg
——————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# expr 5 \* 3
15
——————————————————————————————————————————————————————————————————————————————
#统计字符串的字符个数
[root@bogon ~]# expr length Liumuquan
9
[root@bogon ~]# expr length Liumuquan@123
13
——————————————————————————————————————————————————————————————————————————————
#逻辑判断
[root@bogon ~]# expr 5 \> 6
0
[root@bogon ~]# expr 8 \> 6
1
——————————————————————————————————————————————————————————————————————————————
#expr的模式匹配功能
[root@bogon ~]# expr Liumuquan ":" ".*"
9
[root@bogon ~]# expr Liumuquan ":" ".*q"
6
[root@bogon ~]# expr Liumuquan ":" ".*q*"
9
脚本练习
指定目录下不允许出现除图片格式外的文件,使用脚本将不合规的文件显示出来,并可以二次开发增加删除功能(使用变量实现)。
#!/bin/bash
# 指定路径
path="/root/picture"
# 遍历指定路径内的所有文件
for file in $path/*; do
# 使用expr命令获取文件的后缀名
# \( \)表示一个捕获组,.表示匹配任意字符,*表示匹配前面的字符零次或多次。所以\(.*\)表示匹配任意长度的字符,可以用前面的子串截取方法代替
extension=$(expr "$file" : '.*\.\(.*\)')
# 如果后缀名为空,则跳过
if [ -z "$extension" ]; then
continue
fi
# 判断后缀名是否为图片格式(这里假设图片格式为jpg、png、gif)
# 网安概念中,白名单使用优先级高于黑名单
if [ "$extension" != "jpg" ] && [ "$extension" != "png" ] && [ "$extension" != "gif" ]; then
echo "非图片格式文件:$file"
# 可以选择删除非图片文件的操作,比如: rm -rf "$file"
fi
done
5.bc命令
命令行计算器,可支持小数计算,有两种操作方式,分别为交互式操作和结合管道符操作,示例如下:
[root@bogon ~]# bc -l #增加-l参数后续可以指定精确度
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
scale=10 #指定精确度
3.1415926*3.456
10.8573440256
6.6666666/2.22
3.0030029729
————————————————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# echo "scale=10; 10/3" | bc
3.3333333333
[root@bogon ~]# a=5
[root@bogon ~]# b=`echo "scale=6; $a / 3" | bc`
[root@bogon ~]# echo $b
1.666666
案例练习:计算出1~50的总和
[root@bogon ~]# echo {1..50}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
[root@bogon ~]# echo {1..50} | tr " " "+"
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50
[root@bogon ~]# echo {1..50} | tr " " "+"|bc
1275
———————————————————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# seq -s "+" 50 #-s指定分隔符为+号
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50
[root@bogon ~]# seq -s "+" 50 | bc
1275
———————————————————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# echo $((`seq -s " + " 50`))
1275
———————————————————————————————————————————————————————————————————————————————————————————
[root@bogon ~]# seq -s " + " 50 | xargs expr
1275
#xargs是用来接收多个参数的 所以需要在+号两边加上空格
6.awk计算
这里只展示awk的计算功能,awk同样支持小数计算
[root@bogon ~]# echo "3.4 6.2" | awk '{print $1+$2}'
9.6
[root@bogon ~]# echo "3.4 6.2" | awk '{print $1*$2}'
21.08
7.中括号
示例如下:
[root@bogon ~]# num=5
[root@bogon ~]# res=$[num+6]
[root@bogon ~]# echo $res
11
至自己:
关于计算的笔记到这里基本就结束了,主要是翻看自己网安工作中保留的的一些脚本进行的整理,可能不算全面,但确实是在工作中用的比较多的。
比如白名单设置,网站存活状态探测等,可能这些部分对于初学者并不算友好,但是实践才是记忆的最好方式。
如果说运维很像文科的话,开发就是实在的理科学习,多写几个脚本,阅读大神的解法,才是效率最高的学习或复习之路。