Shell入门-Shell变量数值计算

Shell变量数值计算

算术运算符

Shell中常见的算术运算符号

  • +:加法
  • -:减法或负号
  • *:乘法
  • /:除法
  • %:取余
  • **:幂运算
  • ++:增加
  • --:减少
  • !:逻辑非
  • &&:逻辑与
  • ||:逻辑或
  • < <= > >=:比较符号
  • == != =:比较符号,对于字符串“=”也可以表示相当于
  • << >>:向左移位、向右移位
  • ~:按位取反
  • |:按位异或
  • &:按位与
  • ^:按位或
  • = += -= *= /= %=:赋值运算

算术运算命令

  • (()):用于整数运算
  • let:用于整数运算,类似于(())
  • expr:用于整数运算
  • bc:适合整数及小数运算
  • $[]:用于整数运算
  • awk:适合整数及小数运算
  • declare:定义变量值和属性

(())

双小括号(())的作用是进行数值运算与数值比较。

简单的数值运算:

[root@localhost shell]# echo $((1+1))
2
[root@localhost shell]# echo $((6-3))
3
[root@localhost shell]# ((i=5))
[root@localhost shell]# ((i=i*2))
[root@localhost shell]# echo $i
10
[root@localhost shell]# 

复杂的综合运算

[root@localhost shell]# ((a=1+2**3-4%3))
[root@localhost shell]# echo $a
8
[root@localhost shell]# b=$((1+2**3-4%3))
[root@localhost shell]# echo $b
8
[root@localhost shell]# echo $((1+2**3-4%3))
8
[root@localhost shell]# a=$((100*(100+1)/2))
[root@localhost shell]# echo $a
5050
[root@localhost shell]# echo $((100*(100+1)/2))
5050
[root@localhost shell]# 

特殊运算符号

[root@localhost shell]# a=8
[root@localhost shell]# echo $((a=a+1))
9
[root@localhost shell]# echo $((a+=1))
10
[root@localhost shell]# echo $((a**2))
100

比较及判断

[root@localhost shell]# echo $((3<8))
1
[root@localhost shell]# echo $((8<3))
0
[root@localhost shell]# echo $((8=8))
-bash: 8=8: 尝试给非变量赋值 (错误符号是 "=8")
[root@localhost shell]# echo $((8==8))
1
[root@localhost shell]# if ((8>7&&5==5))
> then
> echo yes
> fi
yes
[root@localhost shell]# 

++ --的使用,和Java中的类似

[root@localhost shell]# a=10
[root@localhost shell]# echo $a
10
[root@localhost shell]# echo $((a++))
10
[root@localhost shell]# echo $a
11
[root@localhost shell]# echo $((a--))
11
[root@localhost shell]# echo $a
10
[root@localhost shell]# echo $((++a))
11
[root@localhost shell]# echo $a
11
[root@localhost shell]# echo $((--a))
10
[root@localhost shell]# echo $a
10
[root@localhost shell]# 

总结:

  1. (())表达式在命令行执行时不需要加$符号,直接使用((6%2))形式即可,但是如果需要输出,就要加$符,例如:echo $((6%2))
  2. (())里的所有字符之间没有空格、有一个或多个空格都不会影响结果

(())使用实例:

[root@localhost shell]# cat test-arithmetic-001.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      test-arithmetic-001.sh
#Description:   This is a test script.
#***********************************************
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 shell]# sh test-arithmetic-001.sh 
a-b=4
a+b=8
a*b=12
a/b=3
a**b=36
a%b=0

我们可以改造上面的脚本,通过命令行传参,修改变量的取值来源:

[root@localhost shell]# cat test-arithmetic-001.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      test-arithmetic-001.sh
#Description:   This is a test script.
#***********************************************
a=$1
b=$2
c=$#

if [ 2 -ne $c ]
then 
    echo "please input two args"
    exit
fi


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 shell]# sh test-arithmetic-001.sh 
please input two args
[root@localhost shell]# sh test-arithmetic-001.sh 6 2
a-b=4
a+b=8
a*b=12
a/b=3
a**b=36
a%b=0

let

  • let运算命令的语法格式为:let赋值表达式
  • let赋值表达式的功能等同于((赋值表达式))
[root@localhost shell]# i=2
[root@localhost shell]# i=i+8
[root@localhost shell]# echo $i
i+8
[root@localhost shell]# unset i
[root@localhost shell]# i=2
[root@localhost shell]# let i=i+8
[root@localhost shell]# echo $i
10
[root@localhost shell]# 

创建一个脚本监控Web服务状态,如果访问两次都失败,则报警。

提示:实际上wget命令有自动重试的功能,--tries=1参数就是

[root@localhost shell]# vim $(date +%F)_checkurl.sh
[root@localhost shell]# cat 2021-03-08_checkurl.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      2021-03-08_checkurl.sh
#Description:   This is a test script.
#***********************************************

checkUrl() {
#重试次数
    timeout=5
    #失败次数
    fails=0
    #成功次数
    success=0
	#默认死循环
    while true
    do
        wget --timeout=$timeout --tries=1 http://10.185.62.161 -q -O /dev/null
        #$?结果为0表示上一条命令执行结果成功
        if [ $? -ne 0 ]
        then
        	#不为0表示失败,失败次数+1
            let fails=fails+1
        else
        	#为0成功,成功次数+1
            let success+=1
        fi
		#成功次数大于等于1,输出success,并退出
        if [ $success -ge 1 ]
        then
            echo success
            exit 0
        fi
		#失败次数大于等于2,输出错误信息,并退出
        if [ $fails -ge 2 ]
        then
            Critical="sys is down..."
            echo $Critical
            exit 2;
        fi
    done
}
#执行上面定义的函数
checkUrl

监控执行结果:

[root@localhost shell]# sh -x 2021-03-08_checkurl.sh 
+ checkUrl
+ timeout=5
+ fails=0
+ success=0
+ true
+ wget --timeout=5 --tries=1 http://10.185.62.161 -q -O /dev/null
+ '[' 0 -ne 0 ']'
+ let success+=1
+ '[' 1 -ge 1 ']'
+ echo success
success
+ exit 0

expr

expr的用途

  • 整数运算
  • 相关字符串长度、匹配等运算处理

1.expr用于计算

语法:expr Expression

[root@localhost shell]# expr 2+2
2+2
[root@localhost shell]# expr 2 + 2
4
[root@localhost shell]# expr 2 * 2
expr: 语法错误
[root@localhost shell]# expr 2 \* 2
4
[root@localhost shell]# expr 2 / 2
1
[root@localhost shell]# 

注意事项:

  • 运算符及用于计算的数字左右都至少有一个空格,否则会报错。
  • 使用乘号时,必须用反斜线屏蔽其特定含义,因为Shell可能会误解星号的含义。

2.expr配合变量计算

expr在Shell中可配合变量进行计算,但需要用反引号将计算表达式括起来。

[root@localhost shell]# i=5
[root@localhost shell]# i=`expr $i + 6`
[root@localhost shell]# echo $i
11
[root@localhost shell]# 

使用expr来判断一个字符串是否为整数,原理是利用以expr做计算时变量或字符串必须是整数的规则,把一个变量或字符串和一个已知的整数(非0)相加,看命令返回的值是否为0。如果为0,就认为做加法的变量或字符串为整数,否则就不是整数。

[root@localhost shell]# i=5
[root@localhost shell]# expr $i + 6 &>/dev/null #<== &>/dev/null表示不保留任何输出
[root@localhost shell]# echo $?
0
[root@localhost shell]# i=oldboy
[root@localhost shell]# expr $i + 6 &>/dev/null
[root@localhost shell]# echo $?
2
[root@localhost shell]# 

判断输出内容是否为空

[root@localhost shell]# vim $(date +%F)_expr.sh
[root@localhost shell]# cat 2021-03-08_expr.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      2021-03-08_expr.sh
#Description:   This is a test script.
#***********************************************
expr $1 + 1 >/dev/null 2>&1
[ $? -eq 0 ] &&echo int||echo chars
[root@localhost shell]# sh 2021-03-08_expr.sh oldboy
chars
[root@localhost shell]# sh 2021-03-08_expr.sh 11
int

编写一个输入两个参数进行计算的程序,并且能判断传参个数和通过expr判断传入的参数是否为整数。

[root@localhost shell]# cat calculate_expr.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      calculate_expr.sh
#Description:   This is a test script.
#***********************************************

a=$1
b=$2
c=$#

if [ 2 -ne $c ]
then
    echo "please input two args..."
    exit 1;
fi

for i in $*;
do
    expr $i + 1 > /dev/null 2>&1
    if [ $? -eq 0 ] 
    then 
        echo "$i is int"
    else 
        echo "$i is chars,please retry and input int" 
        exit 1;
    fi
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))"

通过expr计算字符串的长度

[root@localhost shell]# char="i am oldboy"
[root@localhost shell]# expr length "$char"
11
[root@localhost shell]# echo ${#char}
11
[root@localhost shell]# echo ${char}|wc -L
11
[root@localhost shell]# echo ${char}|awk 'print length($0)'
awk: cmd. line:1: print length($0)
awk: cmd. line:1: ^ syntax error
[root@localhost shell]# echo ${char}|awk 'print length($O)'
awk: cmd. line:1: print length($O)
awk: cmd. line:1: ^ syntax error
[root@localhost shell]# echo ${char}|awk '{print length($0)}'
11

打印下面语句中字符数不大于6的单词:I am oldboy linux welcome to our training。注意被循环的语句,不能用“”包裹

[root@localhost shell]# cat word_length.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      word_length.sh
#Description:   This is a test script.
#***********************************************

for n in "i am oldboy linux welcome to our training"
do
    if [ `expr length $n` -le 6 ]
    then
        echo $n
    fi

    if [ ${#n} -le 6 ]
    then
        echo $n
    fi
[root@localhost shell]# sh word_length.sh 
expr: 语法错误
word_length.sh: 第 13 行:[: -le: 期待一元表达式
[root@localhost shell]# cat word_length.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      word_length.sh
#Description:   This is a test script.
#***********************************************

for n in i am oldboy linux welcome to our training
do
    if [ `expr length $n` -le 6 ]
    then
        echo $n
    fi

    if [ ${#n} -le 6 ]
    then
        echo $n
    fi
[root@localhost shell]# sh word_length.sh 
i
i
am
am
oldboy
oldboy
linux
linux
to
to
our
our

获取expr的帮助:

[root@localhost shell]# man expr
[root@localhost shell]# 

bc

bc是UNIX/Linux下的计算器,因此,除了可以作为计算器来使用,还可以作为命令行计算工具使用。

[root@localhost shell]# 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'. 
1+1
2
3*3
9

使用bc实现整数和小数的运算

[root@localhost shell]# echo 3+5|bc
8
[root@localhost shell]# echo 3.3+5.5|bc
8.8
[root@localhost shell]# echo "scale=2;355/113"|bc
3.14
[root@localhost shell]# echo "scale=6;355/113"|bc
3.141592
[root@localhost shell]# 

bc配合变量运算

[root@localhost shell]# i=5
[root@localhost shell]# i=`echo $i+6|bc`
[root@localhost shell]# echo $i
11

提示:根据bc所具有的特殊性来看,如果是小数,则选择bc运算没有问题(老男孩推荐awk);若是整数场景,可用(())letexpr等。

通过一条命令计算输出1+2+3+…+10的表达式,并计算出结果,请使用bc命令计算。

生成1+2+3+…+10的方法有如下两种:

  • seq -s "+" 10:seq是生成数字序列,-s是指定数字序列
  • echo {1..10}|tr " " "+":{1..10}是生成以空格为间隔的数字序列,并交给tr将空格替换为+号
[root@localhost shell]# seq -s "+" 10
1+2+3+4+5+6+7+8+9+10
[root@localhost shell]# echo {1..10}|tr " " "+" 
1+2+3+4+5+6+7+8+9+10

计算方法:

[root@localhost shell]# echo $(seq -s '+' 10)=`seq -s "+" 10|bc`
1+2+3+4+5+6+7+8+9+10=55
[root@localhost shell]# echo "`seq -s '+' 10`="$((`seq -s "+" 10`))
1+2+3+4+5+6+7+8+9+10=55
[root@localhost shell]# echo `seq -s '+' 10`=`seq -s "+" 10|xargs expr`
1+2+3+4+5+6+7+8+9+10=1+2+3+4+5+6+7+8+9+10
[root@localhost shell]# echo `seq -s '+' 10`=`seq -s " + " 10|xargs expr`
1+2+3+4+5+6+7+8+9+10=55
[root@localhost shell]# echo `seq -s "+" 10`=$(echo $[`seq -s `])
seq:选项需要一个参数 -- s
Try 'seq --help' for more information.
1+2+3+4+5+6+7+8+9+10=0
[root@localhost shell]# echo `seq -s "+" 10`=$(echo $[`seq -s "+" 10`])
1+2+3+4+5+6+7+8+9+10=55

awk

利用awk进行运算的效果也很好,适合小数和整数,特别是命令行计算,尤其是小数,运算很精确,好用。

[root@localhost shell]# echo "7.7 3.8"|awk '{print ($1-$2)}'
3.9
[root@localhost shell]# echo "358 113"|awk '{print ($1-3)/$2}'
3.14159
[root@localhost shell]# echo "3 9"|awk '{print ($1+3)*$2}'
54
[root@localhost shell]# 

declare(同typeset)

declare -i 参数可以将变量定义为整形。

[root@localhost shell]# declare -i A=30 B=7
[root@localhost shell]# A=A+B
[root@localhost shell]# echo $A
37
[root@localhost shell]# 

$[]

[root@localhost shell]# i=5
[root@localhost shell]# i=$[i+6]
[root@localhost shell]# echo $i
11
[root@localhost shell]# echo $[2*3]
6
[root@localhost shell]# echo $[2**3]
8
[root@localhost shell]# echo $[3/5]
0
[root@localhost shell]# echo $[3/2]
1
[root@localhost shell]# echo $[3%5]
3
[root@localhost shell]# echo $[ 3 % 5 ]
3

read命令

Shell变量除了可以直接赋值或脚本传参外,还可以使用read命令从标准输入中获得,read为bash内置命令,可通过help read查看帮助。

语法格式:read [参数] [变量名]

常用参数:

  • -p prompt:设置提示信息。
  • -t timeout:设置输入等待的时间,单位默认为秒。
[root@localhost shell]# read -t 10 -p "pls input one num:" num
pls input one num:1
[root@localhost shell]# echo $num
1
[root@localhost shell]# read -p "pls input two number"
pls input two number1
[root@localhost shell]# read -p "pls input two number" a1 a2
pls input two number1 2
[root@localhost shell]# echo $a1
1
[root@localhost shell]# echo $a2
2
[root@localhost shell]# 

使用read来作为脚本的参数

[root@localhost shell]# cat calculate_read.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      calculate_read.sh
#Description:   This is a test script.
#***********************************************
read -t 5 -p "please input two number:" a b

if [ 0 -ne $? ]
then
    echo "timeout,will exit....."
    exit 1;
fi

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 shell]# sh calculate_read.sh
please input two number:1 2
a-b=-1
a+b=3
a*b=2
a/b=0
a**b=1
a%b=1

整合判断输入的是否为整数和输入的个数为2

[root@localhost shell]# cat calculate_read.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          tianhao.luo@hand-china.com
#Version:       1.0
#Date:          2021-03-08
#FileName:      calculate_read.sh
#Description:   This is a test script.
#***********************************************
read -t 5 -p "please input two number:" a b

if [ 0 -ne $? ]
then
    echo "timeout,will exit....."
    exit 1;
fi

[ ${#a} -le 0 ]&&{
echo "the first num is null"
exit 2
}

[ ${#b} -le 0 ]&&{
echo "the second num is null"
exit 3
}

expr $a + 1 &>/dev/null
RETVAL_A=$?
expr $b + 1 &>/dev/null
RETVAL_B=$?

if [ $RETVAL_A -ne 0 -o $RETVAL_B -ne 0 ];then
    echo "one of the num is not num,pls input again..."
    exit 4;
fi


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 shell]# sh calculate_read.sh 
please input two number:a b
one of the num is not num,pls input again...
[root@localhost shell]# sh calculate_read.sh 
please input two number:11 2
a-b=9
a+b=13
a*b=22
a/b=5
a**b=121
a%b=1
[root@localhost shell]# sh calculate_read.sh 
please input two number:1
the second num is null
[root@localhost shell]# sh calculate_read.sh 
please input two number: 1
the second num is null
[root@localhost shell]# 
posted @ 2021-03-08 21:46  春刀c  阅读(462)  评论(0编辑  收藏  举报