zoukankan      html  css  js  c++  java
  • 五、Shell运算

     

    整数值运算

    使用expr命令:只能做整数运算,默认返回计算结果

    格式:

    expr 整数1 运算符 整数2 ...

    整数值可以有变量提供,直接给出运算结果

    +      加法   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 

    例子:

    #!/bin/bash
    #计算用户从终端输入的任意2个数的和
    read -p "请输入第一个数" num1
    read -p "请输入第二个数" num2
    sum=`expr $num1 +  $num2`
    echo "$num1 + $num2 = $sum"

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

    需借助echo输出结果,运算类型与expr类似
    乘法*不用加转义符
    使用变量时,直接指定变量名,不用加$符号

    shell中如何进行算术运算:

    let 算术运算表达式           let C=$A+$B
    $[算术运算表达式]            C=$[$A+$B]
    $((算术运算表达式))           C=$(($A+$B))
    expr 算术运算表达式,
    表达式中各操作数及运算符之间要有空格,
    而且要使用命令引用 C
    =`expr $A + $B`

    表达式的简化

    变量的递增、递减等操作

     

    简写表达式    完整表达式
    i++        i=i+1
    i--       i=i-1
    i*=2      i=i*2
    i+=2      i=i+2
    i-=2      i=i-2
    i%=2     i=i%2

    注意:

    i++:先参与其他操作,后运算
    ++i:先运算,再参与其他操作

    例子:

    i=1
    echo $((++i))
    j=1
    echo $((j++))

    变量的自增/减等操作

    使用let命令

    操作变量值,只运算,不输出结果
    若要查看结果,需借助echo命令
    let:只做运算不返回计算结果,适用于自加和自减运算
    #!/bin/bash
    i=10 
    let i-=2
    echo $i
    let i-=2
    echo $i
    echo -------------------
    i=10 
    let i+=2
    echo $i
    let i+=2
    echo $i

    变量的数值计算

    变量的数值计算常用的有如下几个命令:

    (())、let、expr、bc、$[]

    1)(())用法:(此法很常用)

    如果要执行简单的整数运算,只需将特定的算术表达式用”$((”和”))”括起来即可。

    Shell的算术运算符号常置于”$((“......”))”的语法中。这一语法如同双引号的功能,除了内嵌双引号无需转义。

    范例1:shell的运算实例如下:

    [root@Web ~]# su - zgy
    
    [zgy@Web ~]$ ((a=1+2**3-4%3))
    
    [zgy@Web ~]$ echo $a
    
    8
    
    [zgy@Web ~]$ b=$((1+2**3-4%3))
    
    [zgy@Web ~]$ echo $b
    
    8
    
    [zgy@Web ~]$ echo $((a=1+2**3-4%3))
    
    8

    提示:上面是三种不同的变量计算定义和使用的方式

    [zgy@Web ~]$ echo $((a+=1))  #相当于a=a+1
    
    9
    
    [zgy@Web ~]$ echo $((a++))
    
    9
    
    [zgy@Web ~]$ echo $((a--))
    
    10
    
    [zgy@Web ~]$ echo $((3>2))  #比较大小
    
    1
    
    [zgy@Web ~]$ echo $((3<2))
    
    0
    
    [zgy@Web ~]$ a=$((100*(100+1)/2))
    
    [zgy@Web ~]$ echo $a
    
    5050
    
    [zgy@Web ~]$ echo $((100*(100+1)/2))
    
    5050

    提示:

    1.**为幂运算;%为取模运算(就是除法当中取余数)

    2.上面涉及到的参数变量必须为整数(整型)。不能为小数(浮点数)或者字符串。后面的bc命令可以进行浮点数运算,但一般较少用到。

    3.echo $((a++))和echo $((a--))表示先输出a自身的值,然后再进行++--的运算,echo $((++a))和echo $((--a))表示先进行++--的运算,再输出a自身的值

    记忆方法:变量在前,先输出变量值,变量在后,就是先运算后输出变量的值。

    范例2:--,++在变量前后的举例理解:

    [root@Web ~]# a=10
    
    [root@Web ~]# echo $((a++))   #先输出a的值,因为a为10,所以输出10
    
    10
    
    [root@Web ~]# echo $a  #上面输出a的值后,a自增1,因此为11
    
    11
    
    [root@Web ~]# echo $((a++))
    
    11
    
    [root@Web ~]# echo $a
    
    12
    
    [root@Web ~]# ((a++))
    
    [root@Web ~]# echo $a
    
    13
    
    [root@Web ~]# a=10
    
    [root@Web ~]# echo $((a--))
    
    10
    
    [root@Web ~]# echo $a
    
    9
    
    [root@Web ~]# ((a--))
    
    [root@Web ~]# echo $a
    
    8
    
    [root@Web ~]# echo $((++a))
    
    9
    
    [root@Web ~]# echo $a
    
    9
    
    [root@Web ~]# echo $((++a))
    
    10
    
    [root@Web ~]# echo $a
    
    10
    
    [root@Web ~]# echo $((++a))
    
    11
    
    [root@Web ~]# echo $a
    
    11
    
    [root@Web ~]# echo $((--a))
    
    10
    
    [root@Web ~]# echo $a
    
    10
    
    [root@Web ~]# echo $((--a))
    
    9
    
    [root@Web ~]# echo $a
    
    9

    范例3:定义变量计算的例子:

    [root@Web ~]# myvar=99
    
    [root@Web ~]# echo $(($myvar + 1))   
    
    100
    
    [root@Web ~]# echo $((  $myvar + 1  ))  #(())两边有几个空格不敏感,也可以没有
    
    100
    
    [root@Web ~]# myvar=$(( $myvar + 1 ))  #还可以赋值给变量然后输出变量
    
    [root@Web ~]# echo $myvar
    
    100
    
     

    范例4:各种(())的计算命令行执行例子:

    [root@Web ~]# echo $((100/5))   #除法,取商
    
    20
    
    [root@Web ~]# echo $((100+5))
    
    105
    
    [root@Web ~]# echo $((100*5))
    
    500
    
    [root@Web ~]# echo $((100-5))
    
    95
    
    [root@Web ~]# echo $((100**5)) #幂
    
    10000000000
    
    [root@Web ~]# echo $((100%5))  #取模,余数
    
    0

    范例5:各种(())运算的shell脚本例子

    [root@localhost ~]# cat test.sh
    
    #!/bin/bash
    
    a=6
    
    b=2
    
    echo "a-b =$(($a-$b))"
    
    echo "a+b =$(($a+$b))"
    
    echo "a*b =$(($a*$b))"
    
    echo "a/b =$(($a/$b))"
    
    echo "a**b =$(($a**$b))"
    
    echo "a%b =$(($a%$b))"

    执行结果如下:

    [root@localhost ~]# sh test.sh
    
    a-b =4
    
    a+b =8
    
    a*b =12
    
    a/b =3
    
    a**b =36
    
    a%b =0
    
     

    范例6:这是一个实践考试题,内容如下:

    请把a,b两个变量通过命令行传参的方式实现上面混合运算脚本的功能。

    [root@localhost ~]# cat test1.sh
    
    #!/bin/bash
    
    a=$1
    
    b=$2
    
    echo "a-b =$(($a-$b))"
    
    echo "a+b =$(($a+$b))"
    
    echo "a*b =$(($a*$b))"
    
    echo "a/b =$(($a/$b))"
    
    echo "a**b =$(($a**$b))"
    
    echo "a%b =$(($a%$b))"

    执行结果[root@localhost ~]# sh test1.sh 6 2

    a-b =4
    
    a+b =8
    
    a*b =12
    
    a/b =3
    
    a**b =36
    
    a%b =0

    拓展:请实现一个加、减、乘、除等功能的计算器。通过命令行传参的方式实现上面脚本的功能。

    答案:

    [root@localhost ~]# cat d.sh
    
    #!/bin/bash
    
    echo$(($1))
    
    [root@localhost ~]# cat j.sh
    
    #!/bin/bash
    
    echo $(($1$2$3))
    
    [root@localhost ~]# sh j.sh 4+2
    
    6
    
    [root@localhost ~]# sh j.sh 4-2
    
    2
    
     

    学生例子:(如果敲不需要的内容会退出,待完善)

    [root@localhost ~]# cat yubing_test.sh
    #!/bin/bash
    #add, subtract, multiply and divide  by yubing
    print_usage(){
        printf "Please enter an integer 
    "
        exit 1
    }
    read -p "Please input first number: " firstnum
    if [ -n "`echo $firstnum|sed 's/[0-9]//g' | sed 's/-//g'`" ];then
        print_usage
    fi
    read -p "Please input the operators: " operators
    if [ "${operators}" != "+" ]&&[ "${operators}" != "-" ] && [ "${operators}" != "*" ] && [ "${operators}" != "/" ];then
        echo "please use + - * /"
        exit 1
    fi
    read -p "Please input second number: " secondnum
    if [ -n "`echo $secondnum|sed ' s/[0-9]//g' |sed ' s/-//g'`" ];then
        print_usage
    fi
    echo "${firstnum}${operators}${secondnum}=$((${firstnum}${operators}${secondnum}))"

    执行结果:

    [root@localhost ~]# sh yubing_test.sh
    
    Please input first number: 6
    
    Please input the operators: +
    
    Please input second number: 2
    
    6+2=8
    
    [root@localhost ~]# sh yubing_test.sh
    
    Please input first number: 6
    
    Please input the operators: *
    
    Please input second number: 2
    
    6*2=12

    作业:完成一个简单的四则运算计算器功能

    (2)let命令的用法

    格式:

     let 赋值表达式

    [注]let 赋值表达式功能等同于:((赋值表达式))

    范例1:给自变量i加8

    [root@localhost ~]# i=2
    
    [root@localhost ~]# let i=i+8
    
    [root@localhost ~]# echo $i
    
    10
    
    [root@localhost ~]# i=i+8  #去掉let定义
    
    [root@localhost ~]# echo $i
    
    i+8

    提示:let i=i+8等同于((i=i+8)),但后者效率更高

    范例2:利用let计数监控web服务状态。

    #!/bin/bash
    #监控服务状态
    ServerMonitor(){
        #服务状态监控
        timeout=10
        fails=0
        success=0
        while true
        do
        /usr/bin/wget --timeout=$timeout --tries-1 http://172.16.0.1/ -q -O /dev/null
            if [ $? -ne 0 ]
            then
                let fails=fails+1
                success=0
            else
                fails=0
                let success=1
            fi
            if [ $success -ge 1 ]
            then
                exit 0
            fi
            if [$fails -ge 2 ];then
                Critical=" TMS 应用服务出现故障,请紧急处理!! "
                echo $Critical | mutt -s " 服务 down " www.magedu.com
                exit
            fi
        done
    
    }

    (3)expr (evaluate expressions)命令的用法:

    Expr命令一般用于整数值,但也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令行计算器

    语法:expr Expression

    [root@localhost ~]# expr 2 +2
    
    expr: 语法错误
    
    [root@localhost ~]# expr 2 + 2
    
    4
    
    [root@localhost ~]# expr 2 - 2
    
    0
    
    [root@localhost ~]# expr 2 * 2
    
    expr: 语法错误
    
    [root@localhost ~]# expr 2 * 2
    
    4
    
    [root@localhost ~]# expr 2 / 2
    
    1
    
    [root@localhost ~]# expr 2 ** 2
    
    expr: 语法错误
    
    [root@localhost ~]# expr 3 % 2
    
    1
    
    [root@localhost ~]# expr 2+2
    
    2+2

    提示:

    1、注意:运算符左右都有空格

    2、使用乘号时,必须用反斜线屏蔽其特定含义。因为shell可能会误解星号的含义。

    增量计数

    Expr在循环中可用于增量计算。首先,循环初始化为0,然后循环值加1,反引号的用法为命令替换。最基本的一种是从(expr)命令接受输出并将之放入循环的变量。

    例:给自变量i加1

    [root@localhost ~]# i=0
    
    [root@localhost ~]# i=`expr $i + 1`
    
    [root@localhost ~]# echo $i
    
    1
    
     

    expr $[$a+$b]表达式形式,其中$a$b可为整数值

    [root@localhost ~]# expr $[2+3]
    
    5
    
    [root@localhost ~]# expr $[2*3]
    
    6
    
    [root@localhost ~]# expr $[2**3]
    
    8
    
    [root@localhost ~]# expr $[2/3]
    
    0
    
    [root@localhost ~]# expr $[2%3]
    
    2
    
    [root@localhost ~]# a=5
    
    [root@localhost ~]# b=6
    
    [root@localhost ~]# expr $[$a+$b]
    
    11

    expr将其后的串解释为表达式并计算其值,运算符前后须有空格

    其它特殊的用法

    expr用法ssh-copy-id

     [root@localhost ~]# less /usr/bin/ssh-copy-id
    
        if expr "$1" : ".*.pub" > /dev/null ; then
    # expr : id_dsa.pub:’.
    *.pub’,匹配*.pub格式的文件如果是则为真。例 [root@localhost ~]# expr "id_dsa.pub" : ".*.pub" 10 #这里是匹配后字符数 #man expr STRING : REGEXP anchored pattern match of REGEXP in STRING

    判断文件或字符串的扩展名小案例:

    [root@localhost ~]# expr "test.pub" : ".*.pub" && echo 1 || echo 0
    
    8
    
    1
    
    [root@localhost ~]# expr "test.x" : ".*.pub" && echo 1 || echo 0
    
    0
    
    0

    技巧:通过expr判断变量是否为整数

    [root@localhost ~]# cat judge_init.sh
    
    #!/bin/bash
    
    read -p "plus input:" a
    
    expr $a + 0 &>/dev/null
    
    [ $? -eq 0 ] && echo init || echo chars
    
    [root@localhost ~]# sh judge_init.sh
    
    plus input:q
    
    chars
    
     
    
    [root@localhost ~]# cat judge_init1.sh
    
    #!/bin/bash
    
    while true
    
    do
    
        read -p "plus input:" a
    
        expr $a + 0 &>/dev/null 2>&1
    
        [ $? -eq 0 ] && echo init || echo chars
    
    Done
    
    [root@localhost ~]# sh judge_init1.sh
    
    plus input:123
    
    init
    
    plus input:oldgirl
    
    chars
    
    plus input:123d
    
    chars
    
    plus input:q
    
    chars
    
     

    通过expr 计算字符串的长度

    [root@localhost ~]# chars=`seq -s" " 100`
    
    [root@localhost ~]# echo ${#chars}
    
    291
    
    [root@localhost ~]# echo $(expr length "$chars")
    
    291

    更多应用请man expr查看帮助

    (4)bc命令的用法:

    bc是UNIX下的计算器,它也可以用在命令行下面:

    例:给自变量i加1

    [root@localhost ~]# i=2
    
    [root@localhost ~]# i=`echo $i+1|bc`   #效率低
    
    [root@localhost ~]# echo $i
    
    3

    因为bc支持科学计算,所以这种方法功能非常强大

    [root@localhost ~]# echo 1+1 | bc
    
    2
    
    [root@localhost ~]# echo 3.5+5|bc
    
    8.5
    
    [root@localhost ~]# echo 3.5+5.6|bc
    
    9.1
    
    [root@localhost ~]# echo 3.5-3.1|bc
    
    .4
    
    [root@localhost ~]# echo 3.5-2.1|bc
    
    1.4
    
    [root@localhost ~]# echo "5.23 * 3.13"|bc
    
    16.36
    
    [root@localhost ~]# echo "scale=1;5.23 * 3.13"|bc
    
    16.36
    
    [root@localhost ~]# echo "scale=1;5.23 / 3.13"|bc
    
    1.6
    
    [root@localhost ~]# echo "scale=6;5.23 * 3.13"|bc
    
    16.3699
    
    [root@localhost ~]# echo "scale=6;5.23 * 3.13"|bc -l
    
    16.3699
    
    [root@localhost ~]# echo "scale=3;5.23 / 3.13"|bc -l
    
    1.670
    
    [root@localhost ~]# echo "obase=2;8"|bc   #10进制8转换成2进制
    
    1000
    
    [root@localhost ~]# echo "obase=16;20"|bc  #10进制20转换成16进制
    
     
    
    14

    通过表达式计算

    [root@localhost ~]# seq -s "+" 10
    
    1+2+3+4+5+6+7+8+9+10
    
    [root@localhost ~]# seq -s "+" 10|bc
    
    55

    特点:bc的特点是支持小数运算

    (5)typeset命令的用法:

    使用整数变量直接进行计算

    例如:

    [root@localhost ~]# typeset -i A=1 B=3
    
    [root@localhost ~]# A=A+B
    
    [root@localhost ~]# echo $A
    
    4

    (5)$[]的用法:

     实践操作演示:

    [root@localhost ~]# echo $[ 2 + 3 ]
    
    5
    
    [root@localhost ~]# echo $[ 2 * 3 ]
    
    6
    
    [root@localhost ~]# echo $[2+ 3]
    
    5
    
    [root@localhost ~]# echo $[3-2]
    
    1
    
    [root@localhost ~]# echo $[3*2]
    
    6
    
    [root@localhost ~]# echo $[3/2]
    
    1
    
    [root@localhost ~]# echo $[3**2]
    
    9
    
    [root@localhost ~]# echo $[3%2]
    
    1

    Shell变量的输入

    Shell变量除了可以直接赋值或脚本传参外,还可以使用read命令从标准输入获得。

    [语法格式]

      read [参数][变量名]

    [常见参数]

    -p prompt:设置提示信息

    -t timeout:设置输入等待的时间,单位默认为秒

    范例1:read的基本读入

    [root@localhost ~]# read -p "please input two number:" a1 a2  #红色部分要有空格
    
    please input two number:12 13
    
    [root@localhost ~]# echo $a1 $a2
    
    12 13

    提示:上面read -p 的功能可以用echo和read实现

    echo -n "please input two number:"
    
    read a1 a2

    以上两句和下面的命令相当(-t排除在外)

    [root@localhost ~]# read -t 5 -p "please input two number:" a1 a2

    范例2:实践考试题

    把前面的加减乘除计算的脚本改成通过read方式读入整数变量:

    原始脚本:

    [root@localhost ~]# cat test.sh
    
    #!/bin/bash
    
    a=6
    
    b=2
    
    echo "a-b =$(($a-$b))"
    
    echo "a+b =$(($a+$b))"
    
    echo "a*b =$(($a*$b))"
    
    echo "a/b =$(($a/$b))"
    
    echo "a**b =$(($a**$b))"
    
    echo "a%b =$(($a%$b))
    
     

    答案:

    [root@localhost ~]# cat read_01.sh
    
    #!/bin/bash
    
    read -t 10 -p "plus input two number:" a b
    
    echo "a-b =$(($a-$b))"
    
    echo "a+b =$(($a+$b))"
    
    echo "a*b =$(($a*$b))"
    
    echo "a/b =$(($a/$b))"
    
    echo "a**b =$(($a**$b))"
    
    echo "a%b =$(($a%$b))"
    
     
    
    [root@localhost ~]# sh read_01.sh
    
    plus input two number:6 2
    
    a-b =4
    
    a+b =8
    
    a*b =12
    
    a/b =3
    
    a**b =36
    
    a%b =0

    范例3:利用echo命令替代和read -p的功能

    [root@localhost ~]# cat g.sh
    
    #!/bin/bash
    
    echo -n "please input two number:"
    
    read a b
    
    echo "a-b =$(($a-$b))"
    
    echo "a+b =$(($a+$b))"
    
    echo "a*b =$(($a*$b))"
    
    echo "a/b =$(($a/$b))"
    
    echo "a**b =$(($a**$b))"
    
    echo "a%b =$(($a%$b))"
    
     
    
    [root@localhost ~]# sh g.sh
    
    please input two number:10 5
    
    a-b =5
    
    a+b =15
    
    a*b =50
    
    a/b =2
    
    a**b =100000
    
    a%b =0

    范例4:思考:如果读入的不是整数,或者参数个数不是2个,以上shell脚本的执行会有什么结果?如何解决这两个问题?

    方法1:

    [root@localhost test]# cat read01.sh
    
    #!/bin/bash
    
    while true
    
    do
    
        read -t 10 -p "pls input two number:" a b
    
        expr $a + 0 >/dev/null 2>&1
    
        [ $? -ne 0 ] && continue
    
        expr $b + 0 >/dev/null 2>&1
    
        [ $? -ne 0 ] && continue || break
    
    done
    
     
    
    echo "a-b =$(( $a - $b ))"
    
    echo "a+b =$(( $a + $b ))"
    
    echo "a*b =$(( $a * $b ))"
    
    echo "a/b =$(( $a * $b ))"
    
    echo "a**b =$(( $a ** $b ))"
    
    echo "a%b =$(( $a % $b ))"

    方法2:命令行传参

    [root@localhost test]# cat argv1.sh
    
    #!/bin/bash
    
    a="$1"
    
    b="$2"
    
    Usage() {
    
        echo "USAGE:sh $0 num1 num2"
    
        exit 1
    
    }
    
    if [ $# -ne 2 ];then
    
        Usage
    
    fi    
    
     
    
    expr $a + 0 >/dev/null 2>&1
    
    [ $? -ne 0 ] && Usage
    
    expr $b + 0 >/dev/null 2>&1
    
    [ $? -ne 0 ] && Usage
    
     
    
    echo "a-b =$(( $a - $b ))"
    
    echo "a+b =$(( $a + $b ))"
    
    echo "a*b =$(( $a * $b ))"
    
    echo "a/b =$(( $a / $b ))"
    
    echo "a**b =$(( $a ** $b ))"
    
    echo "a%b =$(( $a % $b ))"
    
    [root@localhost ~]# sh argv_01.sh kk yy
    
    USAGE:sh argv_01.sh num1 num2
    
    [root@localhost ~]# sh argv_01.sh kk 22
    
    USAGE:sh argv_01.sh num1 num2
    
    [root@localhost ~]# sh argv_01.sh 33 22
    
    a-b =11
    
    a+b =55
    
    a*b =726
    
    a/b =1
    
    a**b =-7228359672964211007
    
    a%b =11
    
    [root@localhost ~]# sh argv_01.sh 6 4
    
    a-b =2
    
    a+b =10
    
    a*b =24
    
    a/b =1
    
    a**b =1296
    
    a%b =2
    
     

     

  • 相关阅读:
    统计学基础
    ip地址分类
    OSI七层协议与TCP/IP模型、三次握手与四次挥手
    计算机编码
    [HNOI2008]Cards
    P4309 [TJOI2013]最长上升子序列
    P3794 签到题IV
    P2605 [ZJOI2010]基站选址
    UVA10791
    P3825 [NOI2017]游戏
  • 原文地址:https://www.cnblogs.com/zhongguiyao/p/8983262.html
Copyright © 2011-2022 走看看