shell基础-数值运算、条件测试、选择分支
2019-04-09 00:16
591 查看
对于脚本的用途,我们也可以用来处理相关的运算的问题,可以大大方便我们的工作。下面我们来看一下shell脚本的数值运算,条件测试以及if判断语句
数值运算
数值运算整数运算小数运算四则运算运算工具- 四则运算
类型 | 公式 |
---|---|
加法 | num1 + num2 |
减法 | num1 - num2 |
乘法 | num1 * num2 |
除法 | num1 / num2 |
-取余运算
-求模: **num1 % num2**
- expr 运算工具
–计算指定的表达式,并输出结果
–格式:expr 整数1 运算符 整数……
–乘法操作操作采用 \* 、’*’ 转义, 避免被作为shel通配符
注意: 符号两边都需要有空格
类型 | 运算符 | 示例 |
---|---|---|
加法 | + | expr 43 + 21、 expr $X + $Y |
减法 | - | expr 43 - 21、 expr $X - $Y |
乘法 | * | expr 43 \* 21、 expr $X \* $Y |
除法 | / | expr 43 / 21、 expr $X / $Y |
取余数 | % | expr 43 % 21、 expr $X % $Y |
[root@room13pc46 ~]# x=1234 [root@room13pc46 ~]# expr $x + 78 1312 [root@room13pc46 ~]# expr $x -78 #注意每个符号之间必须要有空格 expr: 语法错误 [root@room13pc46 ~]# expr $x - 78 1156 [root@room13pc46 ~]# expr $x \* 78 #避免被作为shel通配符 可以加上 \ 或者 ‘’ 进行转义 96252 [root@room13pc46 ~]# expr $x '*' 78 96252 [root@room13pc46 ~]# expr $x % 78 #注意:取模的结果不会大于除数“78” 64 [root@room13pc46 ~]#
- $[ ]、$(())算式替换
–表达式:使用 $[ ] 或者 $()
–乘法操作无需要转义,运算符两侧可以无空格
–引用变量时,可以省略$符号
–计算结果替换表达式本身,可结合echo输出
[root@svr5 ~]# X=1234 [root@svr5 ~]# echo $[X+78] #在[ ] 中可以进行过i任意运算,但是不可以运算小数 1312 [root@svr5 ~]# echo $[X*78] 96252 [[root@room13pc46 ~]# a=10;b=10 [root@room13pc46 ~]# expr $a + $b #需要在每个变量前面加上$ 20 [root@room13pc46 ~]# echo $[a+b] #在多个变量运算时,需要加 $ 20 [root@room13pc46 ~]# echo $[X%78] 64
- let工具
-expr或$[]、$(())方式只进行运算,并不会改变变量的值
-对变量进行操作,不需要写符号,不显示结果
-在进行运算时,可以创建变量
-可以改变变量的值,支持自增、减写法。
[root@room13pc46 ~]# a=10 [root@room13pc46 ~]# expr $a + 2 12 [root@room13pc46 ~]# echo $a 10 [root@room13pc46 ~]# echo $[ a+2] 12 [root@room13pc46 ~]# echo $a 10 #a和b的值没有发生改变 [root@room13pc46 ~]# let a=a+b [root@room13pc46 ~]# echo $a 20 #可以改变a的值 [root@room13pc46 ~]# let a++ #支持自增操作 [root@room13pc46 ~]# echo $a 21 [root@room13pc46 ~]# expr a++ #expr并不支持自增操作 a++ [root@room13pc46 ~]# echo $a 21
- 同时let支持一些主流的写法和简写
[root@svr5 ~]# let X++; echo $X # X++ == (X=X+1) [root@svr5 ~]# let X--; echo $X # X-- == (X=X-1) [root@svr5 ~]# let X+=78 ; echo $X # X+=78 == (X=X+78) [root@svr5 ~]# let X-=78 ; echo $X # X-=78 == (X=X-78) [root@svr5 ~]# let X*=78 ; echo $X # X*=78 == (X=X*78) [root@svr5 ~]# let X/=78 ; echo $X # X/=78 == (X=X/78) [root@svr5 ~]# let X%=78 ; echo $X # X%=78 == (X=X%78)
- bc 小数运算工具
—交互运算,可以计算小数之间的运算
—expr、let、$[ ] ,无法准确运算小数
[root@room13pc46 ~]# 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.34 + 2.54 14.88 23.25+3 26.25 12.0*1.1 13.2 quit #输入quit就可以退出bc交互环境 [root@room13pc46 ~]#
注意: 1. Linux中每一条任务之间,用 " ;" 来分隔;2。bc 所运算的环境式交互式,在脚本应用当中的bc的使用显然不合理。这是我们可以结合**echo 和 |**的操作,来实现bc的脚本应用
[root@room13pc46 ~]# echo '34+5.678' | bc 39.678 [root@room13pc46 ~]# echo '10/3'|bc 3 [root@room13pc46 ~]# echo 'scale =4;10/3'|bc #小数位的长度可采用scale=N限制 3.3333 [root@room13pc46 ~]#
条件测试操作
- 使shell脚本获得识别能力,为命令的执行提供最直接的识别依据
- 如:文件或者目录的读、写状态;数值大小、字符串是否匹配、多条件组合等。
- 语法格式
使用“test 表达式”或者[ 表达式 ]都可以,表达式两边至少要留一个空格。
条件测试操作本身不显示出任何信息。测试的条件是否成立主要体现在命令执行后的返回状态
(即 $?),所以可以在测试后查看变量$?的值来做出判断,或者结合&&、||等逻辑操作显示出结果(或作其他操作) 。
[root@room13pc46 ~]# test "a= a" [root@room13pc46 ~]# echo $? #0 表示正确,1表示错误 0 [root@room13pc46 ~]# [ a == b ] [root@room13pc46 ~]# echo $? 1 #表示错误
- 字符串测试
- == 比较两个字符串是否相同
#检查当前用户是否为root #以root身份执行 [root@room13pc46 ~]# [ $USER == "root" ] [root@room13pc46 ~]# echo $? 0 #结果正确 [root@room13pc46 ~]# su - lisi #当切换普通用户后, [lisi@room13pc46 ~]$ [ $USER == "root" ] [lisi@room13pc46 ~]$ echo $? 1 #结果错误 [lisi@room13pc46 ~]$
- != 比较两个字符串是否不相同
#检查当前用户是否为root #以root身份执行 [root@room13pc46 ~]# [ $USER != "root" ] [root@room13pc46 ~]# echo $? 1 #结果错误 [root@room13pc46 ~]# su - lisi #当切换普通用户后, [lisi@room13pc46 ~]$ [ $USER != "root" ] [lisi@room13pc46 ~]$ echo $? 0 #结果正确 [lisi@room13pc46 ~]$
- 一行执行多条命令的情况
# A && B //仅当A命令执行成功,才执行B命令 # A || B //仅当A命令执行失败,才执行B命令 # A ; B //执行A命令后执行B命令,两者没有逻辑关系 # A && B || C //1.当A执行成功,会执行B不会执行C; 2.当A执行失败,B不会执行,C会执行
- -z 检查变量的值是否未设置(空值)
[lisi@room13pc46 ~]$ var1="nb";var2="" [lisi@room13pc46 ~]$ [ -z "$var1" ] && echo "空值" || echo "非空值" #""表示以字符形式呈现 非空值 [lisi@room13pc46 ~]$ [ -z $var1 ] && echo "空值" || echo "非空值" 非空值 [lisi@room13pc46 ~]$ [ -z "$var2" ] && echo "空值" || echo "非空值" 空值 [lisi@room13pc46 ~]$ [ ! -z "$var2" ] && echo "空值" || echo "非空值" # ! 和 [ 、-z 之间有空格 非空值 [lisi@room13pc46 ~]$ [ ! -z $var1 ] && echo "空值" || echo "非空值" 空值 [lisi@room13pc46 ~]$ [ -n "$var1" ] && echo "空值" || echo "非空值" 空值
> 还有一个-n可以测试变量是否不为空(相当于! -z)。
- 整数值比较
- 参与比较的必须是整数(可以调用变量),比较非整数值时会出错:
[lisi@room13pc46 ~]$ a=20.4 [lisi@room13pc46 ~]$ [ $a -eq 20 ] #不支持小数比较 -bash: [: 20.4: 期待整数表达式 [lisi@room13pc46 ~]$
- 大小比较
符号 | 含义 |
---|---|
-eq | 等于(Equal) |
-ne | 大于等于(Equal) |
-gt | 大于等于(Equal) |
-lt | 小于(Equal) |
-le | 小于等于() |
#例子: [lisi@room13pc46 ~]$ [ $x -eq 21 ] && echo "相等" || echo "不等于" 不等于 [lisi@room13pc46 ~]$ [ $x -eq 20 ] && echo "相等" || echo "不等于" 相等 [lisi@room13pc46 ~]$
- 例子1:使用位置变量创建添加用户的脚本,如果用户没有输入用户名,则退出脚本
#! /bin/bash #使用位置变量创建添加用户的脚本,如果用户没有输入用户名,则退出脚本 read -p "请输入用户名" u [ -z $u ] && exit useradd $u echo “用户创建成功”
- 例子2:每分钟检测系统中登陆帐号的数量,如果大于等于3人登陆,发邮件警告"
解题思路:who: 是查看当前用户登陆数量,然后可以利用 "wc -l " 统计行数即可实现检测当前用户数量.
在利用管道来实现判断操作.
最后在通过计划任务来实现每分钟发邮件.
[root@room13pc46 workplace] vim long_worring.sh #!/bin/bash #每分钟检测系统中登陆帐号的数量,如果大于等于3人登陆,发邮件警告 s=`who | wc -l` [ s -ge 3 ] && echo "worring 操作3人登陆当前系统!!!" -s worring root [root@room13pc46 workplace]# crontab -e #建立计划任务 * * * * * /root/workplace/long_worring.sh
测试:
在虚拟机上执行这脚本,和计划任务…然后多开几个终端连接这个虚拟机.
- 识别文件/目录状态
符号 | 含义 |
---|---|
-e | 判断文件是否存在 (不管是目录还是文件) |
-d | 判断对象是否为目录且存在 |
-f | 判断对象是否为文件且存在 |
-r | 判断对象是否可读 |
-w | 判断对象是否可写 |
-x | 判断对象是否可执行 |
注意:以上选项(除: x 外)均对root无效. x权限对普通用户和root均有效
[root@room13pc46 workplace]# ls login.sh makefile #login.sh 是一个可执行文件 [root@room13pc46 workplace]# [ -e login.sh ] #不管是文件还是目录,只要存在就行 [root@room13pc46 workplace]# echo $? 0 [root@room13pc46 workplace]# [ -d login.sh ] #既要存在,又要是目录才行 [root@room13pc46 workplace]# echo $? 1 [root@room13pc46 workplace]# [ -f login.sh ] #要求文件 [root@room13pc46 workplace]# echo $? 0 [root@room13pc46 workplace]#echo "hfsjafkf" > test [root@room13pc46 workplace]
*对于判断有个特殊的情况
[root@room13pc46 workplace]# echo "hfsjafkf" > test [root@room13pc46 workplace]# ls -ld test -rwxr-xr-x 1 root root 9 4月 8 15:38 test [root@room13pc46 workplace]# chmod 000 test [root@room13pc46 workplace]# ls [root@room13pc46 workplace]# ls -ld test ---------- 1 root root 9 4月 8 15:38 test login.sh test [root@room13pc46 workplace]# [ -r test ] [root@room13pc46 workplace]# echo $? 0 [root@room13pc46 workplace]# [ -x test ] [root@room13pc46 workplace]# echo $? 1 [root@room13pc46 workplace]#
- 例子3 利检测$1 目录是否存在,有则退出,无则创建
#!/bin/bash #利检测$1 目录是否存在,有则退出,无则创建 [ -d $1 ] && exit mkdir $1 echo "文件创建成功" [root@room13pc46 workplace]# ls abc login.sh test [root@room13pc46 workplace]# bash Create_file.sh abc [root@room13pc46 workplace]# bash Create_file.sh dcs 文件创建成功 [root@room13pc46 workplace]# ls abc login.sh dsc test
多个条件/操作的逻辑组合
- &&,逻辑与
#给定条件必须都成立,整个测试结果才为真。检查变量X的值是否大于10,且小于30: [root@room13pc46 workplace]# X=20 //设置X变量的值为20 [root@room13pc46 workplace]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES" YES
- || 逻辑或
#只要其中一个条件成立,则整个测试结果为真。 #只要/tmp/、/var/spool/目录中有一个可写,则条件成立: [root@room13pc46 workplace]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK" OK
使用if选择结构
- 格式
#if单分支的语法组成: if 条件测试 #注意: if(空格)[(空格) 1 == 2 (空格)] 每个之间都需要有空格 then 命令序列 fi #if多分支的语法组成: if 条件测试 then 命令序列1 else 例子命令序列2 fi #if多分支的语法组成: if 条件测试1 ;then 命令序列1 elif 条件测试2 ;then 命令序列2 else 命令序列n fi
- 例子4 检测/media/cdrom目录,若不存在则创建
[root@room13pc46 workplace]# vim mountdir.sh #!/bin/bash dir="/media/cdrom" if [ ! -d $dir ];then mkdir -p $dir fi [root@svr5 ~]# ./mountdir.sh
有了/media/cdrom文件夹以后,再次执行上述脚本,实际上不做任何有效操作:
- 例子5 检测并判断指定的主机是否可ping通
分析任务需求
使用ping命令检测目标主机时,人工可直接判断反馈结果,而脚本却不方便。但是当ping测试成功时,执行状态$?的值为0;而ping测试失败时,$?的值不为0。因此在Shell脚本中可以利用这一点来判断ping目标主机的成败。
为了节省ping测试时间,可以只发送3个测试包(-c 3)、缩短发送测试包的间隔秒数(-i 0.2)、等待反馈的超时秒数(-W 1)。比如,检查可ping通的主机:
[root@room13pc46 workplace]# ping -c 3 -i 0.2 -W 1 192.166.4.5 PING 192.166.4.5 (192.166.4.5) 56(84) bytes of data. --- 192.166.4.5 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 419ms [root@room13pc46 workplace]# echo $? 1
—脚本编写:
#!/bin/bash [root@room13pc46 workplace]# vim Ping_test.sh #检测并判断指定的主机是否可ping通 read -p "情输入你要检测的ip:" I ping $I -c 3 -i 0.2 -W 1 &> /dev/null if [ $? -eq 0 ];then #对上一条命令进行判断 echo "通了" else echo "不通" fi
—测试结果:
[root@room13pc46 workplace]# bash Ping_test.sh 情输入你要检测的ip:127.0.0.1 通了 [root@room13pc46 workplace]# bash Ping_test.sh 情输入你要检测的ip:192.166.45.5 通了 [root@room13pc46 workplace]#
- 例子6利用random生成随机数,用户进行猜
[root@room13pc46 workplace]# vim guess_number.sh #!/bin/bash #利用random生成随机数,用户进行猜 a=$[RANDOM%11] read -p "请输入你的数字(1~10):" N [ -z $N ]&& exit #若用户没有输入数字,则退出 if [ $a -eq $N ];then echo "你猜对了" elif [ $N -gt $a ];then echo "你猜大了" else echo "你猜小了" fi
- 测试:
[root@room13pc46 workplace]# bash guess_number.sh 请输入你的数字(1~10):5 你猜小了 [root@room13pc46 workplace]# bash guess_number.sh 请输入你的数字(1~10): [root@room13pc46 workplace]#
- 例子7从键盘读取一个论坛积分,判断论坛用户等级
脚本要求:
大于等于90 神功绝世
大于等于80,小于90 登峰造极
大于等于70,小于80 炉火纯青
大于等于60,小于70 略有小成
小于60 初学乍练
#!/bin/bash #从键盘上读取一个论坛积分,判断用户的等级 read -p "Please input a Num :" Num if [ $Num -ge 90 ];then echo "神功绝世" elif [ $Num -ge 80 ];then echo "登峰造极" elif [ $Num -ge 70 ];then echo "炉火纯青" elif [ $Num -ge 60 ];then echo "略有小成" else echo "出来乍练" fi总结:
- 运算:1.整数运算 ==>expr、let、 $[] 、$(()) 等工具 2.小数运算:bc
- 条件测试:test和 [] 的用法,以及字符串、整数比较,还有文件的判断操作
- 逻辑判断
if选择分支:==>单分支、多分支、以及语法格式,注意空格。
写的不好,请大家见谅哈。
相关文章推荐
- Shell脚本基础、使用变量、条件测试及选择、列表式循环
- Shell脚本基础 、 使用变量 、 条件测试及选择 、 列表式循环
- 数值运算 条件测试 、 if选择结构
- shell:数值运算、条件测试、if判断
- shell基础之一:变量、变量运算及条件测试
- shell中条件测试与整数运算以及脚本选项
- 2、shell条件测试,运算符,选择结构,for循环结构
- shell脚本中的算术运算和条件测试语句
- 1.3 Shell脚本编程基础之条件测试
- shell脚本编程之条件判断,算术运算,整数测试及特殊变量
- Linux学习日记 —— 10.5.1 Shell基础-Bash变量-数值运算与运算符
- linux基础之shell编程(2)-条件判断,算数运算,测试
- 第9课shell脚本基础2-条件测试及控制流
- 3月13号周五课堂练习:对四则运算二进行测试(选择一个条件)
- shell基础-bash变量-数值运算与运算符
- shell脚本之变量、变量类型、条件测试、算术运算、及特殊变量
- Linux新手生存笔记[9]——shell脚本基础2-条件测试及控制流
- bash的算术运算和条件测试语句基础
- LinuxShell脚本编程基础2-变量与数值运算、父shell和子shell
- Shell基础-Bash变量-数值运算与运算符