Shell基础(二):Shell中的数值运算、条件测试操作、使用if选择结构

时间:2021-09-14 23:19:51

一、Shell中的数值运算

目标:

本案例要求熟悉Linux Shell环境的特点,主要练习以下操作:

1> 使用expr、$[ ]、let等整数运算工具:定义变量X=1234,然后计算X与78的四则运算及求模结果
       2> 使用bc实现小数运算操作:以交互方式计算12.34与56.78的四则运算结果,另外再以非交互方式重复上述计算,最多显示4位小数

步骤:

1)使用expr命令

乘法操作应采用 \* 转义,避免被作为Shell通配符;参与运算的整数值与运算操作符之间需要以空格分开,引用变量时必须加$符号。

首先定义变量X=1234,然后分别计算与78的加减乘除和求模运算结果:

[root@svr5 ~]# X=1234                              //定义变量X
    [root@svr5 ~]# expr  $X  +  78                      //加法
    1312
    [root@svr5 ~]# expr  $X  -  78                       //减法
    1156
    [root@svr5 ~]# expr  $X  \*  78                      //乘法,操作符应添加\转义
    96252
    [root@svr5 ~]# expr  $X  /  78                      //除法,仅保留整除结果
    15
    [root@svr5 ~]# expr  $X  %  78                     //求模
    64

2)使用$[]或$(())表达式

乘法操作*无需转义,运算符两侧可以无空格;引用变量可省略 $ 符号;计算结果替换表达式本身,可结合echo命令输出。

同样对于变量X=1234,分别计算与78的加减乘除和求模运算结果:

[root@svr5 ~]# X=1234   
    [root@svr5 ~]# echo $[X+78]
    1312
    [root@svr5 ~]# echo $[X-78]
    1156
    [root@svr5 ~]# echo $[X*78]
    96252
    [root@svr5 ~]# echo $[X/78]
    15
    [root@svr5 ~]# echo $[X%78]
    64

3)使用let命令

expr或$[]、$(())方式只进行运算,并不会改变变量的值;而let命令可以直接对变量值做运算再保存新的值。因此变量X=1234,在执行let运算后的值会变更;另外,let运算操作并不显示结果,但是可以结合echo命令来查看:

[root@svr5 ~]# X=1234  
    [root@svr5 ~]# let y=X+22
    [root@svr5 ~]# echo $y
    1256
    [root@svr5 ~]# let X+=78 ; echo $X                    # X+=78(X=X+78)
    1312
    [root@svr5 ~]# let X-=78 ; echo $X                 # X-=78(X=X-78)
    1234
    [root@svr5 ~]# let X*=78 ; echo $X                 # X*=78(X=X*78)
    96252
    [root@svr5 ~]# let X/=78 ; echo $X                 # X/=78(X=X/78)
    1234
    [root@svr5 ~]# let X%=78 ; echo $X                 # X%=78(X=X%79)
    64

步骤二:小数运算工具

1)bc交互式运算

先执行bc命令进入交互环境,然后再输入需要计算的表达式。以计算小数12.34与5.678的四则运算为例,相关操作如下:

[root@svr5 ~]# 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+56.78                                        //加法
    69.12
    12.34-56.78                                        //减法
    -44.44
    12.34*56.78                                        //乘法
    700.66
    12.34/56.78                                        //除法
    0
    quit                                              //退出交互计算器
    [root@svr5 ~]#

2)bc非交互式运算

将需要运算的表达式通过管道操作交给bc运算。注意,小数位的长度可采用scale=N限制,除此以外也受参与运算的数值的小数位影响。以计算小数12.34与5.678的四则运算为例,相关操作如下:

[root@svr5 ~]# echo 'scale=4;12.34+5.678' | bc
    18.018
    [root@svr5 ~]# echo 'scale=4;12.34-5.678' | bc
    6.662
    [root@svr5 ~]# echo 'scale=4;12.34*5.678' | bc
    70.0665
    [root@svr5 ~]# echo 'scale=4;12.34/5.678' | bc
    2.1733

二、条件测试操作

目标:

本案例要求参考PPT上的示例,分别练习以下条件测试操作:

1> 字符串匹配
        2> 比较整数值的大小
        3> 识别文件/目录的状态
        4> 多个条件/操作的逻辑组合

步骤:

步骤一:条件测试的基本用法

1)语法格式

使用“test 表达式”或者[ 表达式 ]都可以,表达式两边至少要留一个空格。

条件测试操作本身不显示出任何信息。测试的条件是否成立主要体现在命令执行后的返回状态(即 $?),所以可以在测试后查看变量$?的值来做出判断,或者结合&&、||等逻辑操作显示出结果(或作其他操作) 。

步骤二:字符串测试

1)== 比较两个字符串是否相同

检查当前用户是否为root。

当root用户执行时:

[root@svr5 ~]# [ $USER == "root" ]             //测试
    [root@svr5 ~]# echo $?                        //查看结果0为对,非0为错

当普通用户执行时:

[zengye@svr5 ~]$ [ $USER == "root" ]
    [zengye@svr5 ~]$ echo $?

2)!= 比较两个字符串是否不相同

检查当前用户,如果不是root。

当普通用户执行时:

[zengye@svr5 ~]$ [ $USER != "root" ]

当root用户执行时:

[root@svr5 ~]# [ $USER != "root" ]

3)-z 检查变量的值是否未设置(空值)

[root@svr5 ~]# var1="Tarena" ; var2=""
    [root@svr5 ~]# [ -z "$var1" ] && echo "空值" || echo "非空值"
    非空值
    [root@svr5 ~]# [ -z $var2 ] && echo "空值" || echo "非空值"
    空值                                      //变量var2已设置,但无任何值,视为空
    [root@svr5 ~]# [ ! -z $var1 ]                //测试var1是否为非空

步骤三:整数值比较

参与比较的必须是整数(可以调用变量),比较非整数值时会出错:

[root@svr5 ~]# A=20.4
    [root@svr5 ~]# [ $A -gt 10 ]                  //不支持小数比较
    -bash: [: 20.4: integer expression expected

1)-eq 比较两个数是否相等。

[root@svr5 ~]# X=20                          //定义一个测试变量
    [root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等"
    相等
    [root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等"
    不相等

2)-ne 比较两个数是否不相等。

[root@svr5 ~]# [ $X -ne 20 ] && echo "不等于" || echo "等于"
    等于
    [root@svr5 ~]# [ $X -ne 30 ] && echo "不等于" || echo "等于"
    不等于
3)-gt 比较前面的整数是否大于后面的整数。

[root@svr5 ~]# [ $X -gt 10 ] && echo "大于" || echo "否"
    大于
    [root@svr5 ~]# [ $X -gt 20 ] && echo "大于" || echo "否"
    否
    [root@svr5 ~]# [ $X -gt 30 ] && echo "大于" || echo "否"
    否

4)-ge 比较前面的整数是否大于或等于后面的整数。

[root@svr5 ~]# [ $X -ge 10 ] && echo "大于或等于" || echo "否"
    大于或等于
    [root@svr5 ~]# [ $X -ge 20 ] && echo "大于或等于" || echo "否"
    大于或等于
    [root@svr5 ~]# [ $X -ge 30 ] && echo "大于或等于" || echo "否"
    否
5)-lt 比较前面的整数是否小于后面的整数。

[root@svr5 ~]# [ $X -lt 10 ] && echo "小于" || echo "否"
    否
    [root@svr5 ~]# [ $X -lt 20 ] && echo "小于" || echo "否"
    否
    [root@svr5 ~]# [ $X -lt 30 ] && echo "小于" || echo "否"
    小于

6)-le 比较前面的整数是否小于或等于后面的整数。

[root@svr5 ~]# [ $X -le 10 ] && echo "小于或等于" || echo "否"
    否
    [root@svr5 ~]# [ $X -le 20 ] && echo "小于或等于" || echo "否"
    小于或等于
    [root@svr5 ~]# [ $X -le 30 ] && echo "小于或等于" || echo "否"
    小于或等于

7)提取当前登录的用户数,比较是否超过5。

[root@svr5 ~]# who | wc -l                                  //确认已登录的用户数
    4
    [root@svr5 ~]# N=$(who | wc -l)                              //赋值给变量N
    [root@svr5 ~]# [ $N -gt 5 ] && echo "超过了" || echo "没超过"
    没超过
上述赋值给变量N及与5比较的操作,可以简化为如下形式:

[root@svr5 ~]# [ $(who | wc -l) -gt 5 ] && echo "超过了" || echo "没超过"
    没超过

步骤四:识别文件/目录的状态

1)-e 判断对象是否存在(不管是目录还是文件)

[root@svr5 ~]# [ -e "/usr/src/" ] && echo "存在" || echo "不存在"
    存在
    [root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在"
    存在
    [root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在"
    不存在

2)-d 判断对象是否为目录(存在且是目录)

[root@svr5 ~]# [ -d "/usr/src/" ] && echo "是目录" || echo "不是目录"
    是目录
    [root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目录" || echo "不是目录"
    不是目录
    [root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目录" || echo "不是目录"
    不是目录

3)-f 判断对象是否为文件(存在且是文件)

[root@svr5 ~]# [ -f "/usr/src/" ] && echo "是文件" || echo "不是文件"
    不是文件
    [root@svr5 ~]# [ -f "/etc/fstab" ] && echo "是文件" || echo "不是文件"
    是文件
    [root@svr5 ~]# [ -f "/home/nooby" ] && echo "是文件" || echo "不是文件"
    不是文件

4)-r 判断对象是否可读

此测试对root用户无效,无论文件是否设置r权限,root都可读:

[root@svr5 ~]# cp install.log /tmp/rtest.txt          //复制一个文件做测试
    [root@svr5 ~]# chmod -r /tmp/rtest.txt              //去掉所有的r权限
    [root@svr5 ~]# [ -r "/tmp/rtest.txt" ] && echo "可读" || echo "不可读"
    可读                                              //root测试结果仍然可读

切换为普通用户,再执行相同的测试,结果变为“不可读”:

[zengye@svr5 ~]$ [ -r "/tmp/rtest.txt" ] && echo "可读" || echo "不可读"
    不可读

普通用户只对自己拥有r权限的文件或目录,-r测试时结果才成立:

[zengye@svr5 ~]$ ls -l .bashrc
    -rw-r--r-- 1 zengye zengye 124 09-24 16:44 .bashrc
    [zengye@svr5 ~]$ [ -r ".bashrc" ] && echo "可读" || echo "不可读"
    可读

5)-w 判断对象是否可写

此测试同样对root用户无效,无论文件是否设置w权限,root都可写:

[root@svr5 ~]# chmod -w /tmp/rtest.txt             //去掉所有的w权限
    [root@svr5 ~]# ls -l /tmp/rtest.txt              //确认设置结果
    ---------- 1 root root 33139 12-11 10:43 /tmp/rtest.txt
    [root@svr5 ~]# [ -w "/tmp/rtest.txt" ] && echo "可写" || echo "不可写"
    可写

切换为普通用户,可以正常使用-w测试:

[zengye@svr5 ~]$ ls -l /tmp/rtest.txt
    ---------- 1 root root 33139 12-11 10:52 /tmp/rtest.txt
    [zengye@svr5 ~]$ [ -w "/tmp/rtest.txt" ] && echo "可写" || echo "不可写"
    不可写

6)-x 判断对象是否具有可执行权限

这个取决于文件本身、文件系统级的控制,root或普通用户都适用:

[root@svr5 ~]# chmod 644 /tmp/rtest.txt          //重设权限,无x
    [root@svr5 ~]# ls -l /tmp/rtest.txt              //确认设置结果
    -rw-r--r-- 1 root root 33139 12-11 10:52 /tmp/rtest.txt
    [root@svr5 ~]# [ -x "/tmp/rtest.txt" ] && echo "可执行" || echo "不可执行"
    不可执行
    [root@svr5 ~]# chmod +x /tmp/rtest.txt          //添加x权限
    [root@svr5 ~]# [ -x "/tmp/rtest.txt" ] && echo "可执行" || echo "不可执行"
    可执行

步骤五:多个条件/操作的逻辑组合

1)&&,逻辑与

给定条件必须都成立,整个测试结果才为真。

检查变量X的值是否大于10,且小于30:

[root@svr5 ~]# X=20                      //设置X变量的值为20
    [root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
    YES

多个条件组合时,可以使用 [[ .. ]] 界定,比如上述测试可以改为如下:

[root@svr5 ~]# [[ $X -gt 10 && $X -lt 30 ]] && echo "YES"
    YES

2)||,逻辑或

只要其中一个条件成立,则整个测试结果为真。

检查变量X的值是否小于10或者小于30:

[root@svr5 ~]# [[ $X -lt 10 || $X -lt 30 ]] && echo "YES"
    YES

只要/tmp/、/var/spool/目录中有一个可写,则条件成立:

[root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
    OK

三、使用if选择结构

目标:

本案例要求编写3个Shell脚本,分别实现以下目标:

1> 检测/media/cdrom目录,若不存在则创建
       2> 检测并判断指定的主机是否可ping通
       3> 从键盘读取一个论坛积分,判断论坛用户等级,等级分类如下:

大于等于90 神功绝世

大于等于80,小于90 登峰造极

大于等于70,小于80 炉火纯青

大于等于60,小于70 略有小成

小于60 初学乍练

方案:

if单分支的语法组成:

if  条件测试
        then  命令序列
    fi

if双分支的语法组成:

if  条件测试
        then  命令序列1
        else  命令序列2
    fi

if多分支的语法组成:

if  条件测试1
        then  命令序列1
    elif  条件测试2
        then  命令序列2
        else  命令序列n
    fi

if多分支结构实际上相当于多层if嵌套:

if  条件测试1  ; then
        命令序列1
    else
        if  条件测试2  ; then
            命令序列2
        else
            .. ..
            命令序列n
        fi
    fi

步骤:

步骤一:检测/media/cdrom目录,若不存在则创建

1)编写脚本如下:

[root@svr5 ~]# vim chkmountdir.sh
    #!/bin/bash
    MOUNT_DIR="/media/cdrom/"
    if [ ! -d $MOUNT_DIR ]
    then
        mkdir -p $MOUNT_DIR
    fi
    [root@svr5 ~]# chmod +x chkmountdir.sh                  //添加可执行权限

2)测试、验证脚本功能

[root@svr5 ~]# ls -ld /media/cdrom                  //本来没有/media/cdrom目录
    ls: /media/cdrom: 没有那个文件或目录
    [root@svr5 ~]# ./chkmountdir.sh                      //执行脚本
    [root@svr5 ~]# ls -ld /media/cdrom                  //再检查已经有了
    drwxr-xr-x 2 root root 4096 12-11 15:16 /media/cdrom

有了/media/cdrom文件夹以后,再次执行上述脚本,实际上不做任何有效操作:

[root@svr5 ~]# ./chk_bakdir.sh
    [root@svr5 ~]#

步骤二:检测并判断指定的主机是否可ping通

1)分析任务需求

使用ping命令检测目标主机时,人工可直接判断反馈结果,而脚本却不方便。但是当ping测试成功时,执行状态$?的值为0;而ping测试失败时,$?的值不为0。因此在Shell脚本中可以利用这一点来判断ping目标主机的成败。

为了节省ping测试时间,可以只发送3个测试包(-c 3)、缩短发送测试包的间隔秒数(-i 0.2)、等待反馈的超时秒数(-W 3)。比如,检查可ping通的主机:

[root@svr5 ~]# ping -c 3 -i 0.2 -W 3 192.168.4.5
    PING 192.168.4.5 (192.168.4.5) 56(84) bytes of data.
    64 bytes from 192.168.4.5: icmp_seq=1 ttl=64 time=0.131 ms
    64 bytes from 192.168.4.5: icmp_seq=2 ttl=64 time=0.076 ms
    64 bytes from 192.168.4.5: icmp_seq=3 ttl=64 time=0.073 ms
    --- 192.168.4.5 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 402ms
    rtt min/avg/max/mdev = 0.073/0.093/0.131/0.027 ms
    [root@svr5 ~]# echo $?                                  //执行状态表示成功
    0

2)脚本编写参考如下:

[root@svr5 ~]# vim pinghost.sh
    #!/bin/bash
    ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
    if [ $? -eq 0 ] ; then
        echo "Host $1 is up."
    else
        echo "Host $1 is down."
    fi
    [root@svr5 ~]# chmod +x pinghost.sh

3)测试、验证脚本功能

[root@svr5 ~]# ./pinghost.sh 192.168.4.5
    Host 192.168.4.5 is up.
    [root@svr5 ~]# ./pinghost.sh 192.168.4.50
    Host 192.168.4.50 is down.

步骤三:从键盘读取一个论坛积分,判断论坛用户等级

1)脚本编写参考如下:

大于等于90 神功绝世

大于等于80,小于90 登峰造极

大于等于70,小于80 炉火纯青

大于等于60,小于70 略有小成

大于60 初学乍练

[root@svr5 ~]# vim gradediv.sh
    #!/bin/bash
    read -p "请输入积分(0-100):" JF
    if [ $JF –ge 90 ] ; then
        echo "$JF 分,神功绝世"
    elif [ $JF –ge 80 ] ; then
        echo "$JF 分,登峰造极"
    elif [ $JF –ge 70 ] ; then
        echo "$JF 分,炉火纯青"
    elif [ $JF –ge 60 ] ; then
        echo "$JF 分,略有小成"
    else
        echo "$JF 分,初学乍练"
    fi
    [root@svr5 ~]# chmod +x gradediv.sh

3)测试、验证脚本

[root@svr5 ~]# ./gradediv.sh
    请输入积分(0-100):74
    74 分,炉火纯青
    [root@svr5 ~]# ./gradediv.sh
    请输入分数(0-100):68
    68 分,略有小成
    [root@svr5 ~]# ./gradediv.sh
    请输入分数(0-100):87
    87 分,登峰造极

Shell基础(二):Shell中的数值运算、条件测试操作、使用if选择结构的更多相关文章

  1. shell基础二十篇 一些笔记

    shell基础二十篇 转自 http://bbs.chinaunix.net/thread-452942-1-1.html 研讨:Bash 内建命令 read (read命令更具体的说明见博客收藏的一 ...

  2. 在shell script中进行数值运算的两种方法

    方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...

  3. Shell编程(二)——shell的基础知识及常用命令

    shell的基础知识 一.bash有以下特点: 1.记录命令历史 2.指令和文件名补全 3.别名 alias rm='rm -i' 4.通配符 * 0个或多个字符 ?​匹配一个字符 5 输入输出重定向 ...

  4. shell编程基础(二): shell脚本语法之分支语句和循环语句

    一.分支语句 1.条件测试:test [ 命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假,则命令的Exit Status为1(注意与 ...

  5. shell基础(二)

    echo命令 Shell 的 echo 指令是用于字符串的输出. #!/bin/sh read name #读取标准输入的行 echo "$name It is a test" e ...

  6. shell基础之shell相关概念

    一.脚本介绍 1.脚本简单地说就是一条条的文字命令(一些指令的堆积),这些文字命令是可以看到的(如可以用记事本打开查看.编辑). 常见的脚本: JavaScript(JS,前端),VBScript, ...

  7. linux中的数值运算

    一.declare 作用:声明变量类型,bash默认变量为字符串类型的,并且字符串在拼接时直接拼接,不需要加号 使用方法: 二.数值运算 加法运算 a= b= c=$(($a+$b)) echo $c

  8. Shell 02 数据运算/条件测试

    一.整数运算工具 1.使用expr命令(运算两边必须有空格,引用变量时必须加$符号) [root@svr5 ~]# x=10    //定义变量x expr $x + 10      20       ...

  9. shell中的数值运算

    By francis_hao    Oct 2,2017   本文摘录自bash的man手册.   算数运算相关的形式 形式 含义 ((expression)) expression按照下面描述的算术 ...

随机推荐

  1. php上传功能集后缀名判断和随机命名

    form.php <html> <head> <meta http-equiv="content-type" content="text/h ...

  2. window 下如何安装ghost博客

    1.安装nodejs # Node v0.12.x and v4.2+ LTS - supported 我本地安装的是4.2 安装其他版本可能提示系统不兼容 2.安装mysql 3.安装bower 4 ...

  3. &period;Net MVC框架 &plus; WCF 搭建 集群开发

    http://www.cnblogs.com/zhijianliutang/archive/2012/01/28/2258844.html

  4. Jade之条件语句

    条件语句 jade支持js中的if/elseif/else语法. jade: - var user = { description: 'foo bar baz' } - var authorised ...

  5. 双方都在线,qq总是离线发文件

    这是qq支持多地登录后出现的问题. 原因:1.当您传文件给对方,对方是多终端登录(或者开通移动在线功能)的情况下,为了保证对方一定能收到该文件,我们会智能的为用户切换到离线文件,对方会相应在所在的终端 ...

  6. 第二百五十天 how can I 坚持

    html排版,好烦心. 我以为我会哭,但是我没有.---<领悟> 确实是搞不懂自己,到底想要什么?弟弟最近也不知道咋的了,感觉有点不对劲呢. 最近雾霾好严重,希望我们的后代不会知道雾霾是什 ...

  7. codevs 3332 数列 (矩阵乘法)

    /* 裸地矩阵乘法 矩阵很好想的 1 1 0 0 0 1 1 0 0 */ #include<iostream> #include<cstring> #include<c ...

  8. 如何在RecyclerView上面实现&quot&semi;拖放&quot&semi;和&quot&semi;滑动删除&quot&semi;-2

    拖动手柄 在设计一个支持"拖放"的列表时, 通常提供一个在触摸时初始化拖拽的"拖动手柄". 因其可发现性和可用性而被Material Guidelines所推荐 ...

  9. 11&period;2&period;0&period;4 aix下运行第二个节点root&period;sh报错处理

    第二个节点运行root.sh报错如下 Entries will be added to the /etc/oratab file as needed by Database Configuration ...

  10. &dollar;&period;ajax &comma;ajax请求添加请求头,添加Authorization字段

    beforeSend : function(request) { request.setRequestHeader("Authorization", sessionStorage. ...