本文档主要讲解Shell变量的数值计算与实践

基本大纲:

  1.算术运算符和命令介绍

  2.双小括号"(())"数值运算命令实践

  3.let运算命令的用法实践

  4.expr命令的用法实践

  5.bc命令的用法实践

  6.awk实现计算示例

  7.$[ ]符号的运算示例

  8.基于Shell变量输入read命令的运算实践




一:算术运算符和命令介绍


1、算术运算符

           算术运算符                    使用说明
  +、-   加法(或正号)、减法(或负号)。
  *、/、%   乘法、除法、取余。
  **   幂运算。
<、<=、>、>= 比较符号(小于、小于等于、大于、大于等于)
<<、>>  向左移位,向右移位
~、|、&、^ 按位取反、按位异或、按位与、按位或
  !、&&、||   逻辑非(取反)、逻辑与(and)、逻辑或(or)
  ==、!=、=   比较符号(相等、不相等、相当于)。
  =、+=、-=、*=、/=、%=   赋值运算符。例如a+=1等于a=a+1。
  ++、--   增加或减少、可前置也可放在变量结尾 *


2、算术运算命令

  算术运算命令           使用说明
  (())   用于整数运算的常用运算符,效率较高。
  let   用于整数运算,类似于“(())”。
  expr   可用于整数运算。
  bc   Linux下的一个计算器程序(适合整数及小数运算)。
  $[]   用于整数运算。
  awk   awk既可以用于整数运算,也可以用于小数运算。
  declare


  定义变量值和属性,-i参数可以用于定义整型变量,做运算






二:双小括号"(())"数值运算命令实践

1)简单的数值计算示例

[root@localhost practice]# echo $((1+1))

2

[root@localhost practice]# echo $((6-3))

3

[root@localhost practice]# ((i=5))

[root@localhost practice]# ((i=i*2))

[root@localhost practice]# echo $i

10


2)综合算术计算示例

[root@localhost practice]# ((a=1+2**3-4%3))

[root@localhost practice]# echo $a 

8

[root@localhost practice]# b=$((1+2**3-4%3))

[root@localhost practice]# echo $b

8

[root@localhost practice]# echo $((1+2**3-4%3))

8

[root@localhost practice]# a=$((100*(100+1)/2))

[root@localhost practice]# echo $a

5050

[root@localhost practice]# echo $((100*(100+1)/2))

5050


3)特殊运算符号的运算示例

[root@localhost practice]# a=1

[root@localhost practice]# echo $((a=a+1))

2

[root@localhost practice]# echo $((a+=1))

3

[root@localhost practice]# echo $((a**2))

9


4)利用双括号进行比较和判断

[root@localhost practice]# echo $((3<5))    #3<5的结果是成立的,因此输出1,1表示真

1

[root@localhost practice]# echo $((3>5))    #3>5的结果是不成立的,因此输出0,0表示假

0

[root@localhost practice]# echo $((8==8))

1

[root@localhost practice]# if ((6>5&&5==5));then echo "yes";fi

yes


5)在变量前后使用--和++特殊运算符

[root@localhost practice]# a=6

[root@localhost practice]# echo $((a++))    #因为a在运算符++的前面,那么在输出整个表达式,会输出a的值,因为a为6,所有输出为6

6

[root@localhost practice]# echo $a            #执行上面的表达式后,因为有a++,因此a会自增1,因此输出a的值为7

7

[root@localhost practice]# a=6

[root@localhost practice]# echo $((a--))

6

[root@localhost practice]# echo $a

5

[root@localhost practice]# a=10

[root@localhost practice]# echo $a

10

[root@localhost practice]# echo $((--a))    #因为a在运算符--的后面,那么在输出整个表达式,先进行自减 计算,因为a为10,自减1后为9,所以输出9

9

[root@localhost practice]# echo $a            #执行上面的表达式后,a自减1,所有为9

9

[root@localhost practice]# echo $((++a))    

10

[root@localhost practice]# echo $a

10

经验小结:

变量a在运算符之前,输出的表达式的值为a本身,然后a自增或自减

变量a在运算符之后,输出的表达式会先进行自增或自减, 表达式的值就是自增或自减后a的值


6)通过“(())"运算后赋值给变量

[root@localhost practice]# b=99

[root@localhost practice]# echo $((b+1))

100

[root@localhost practice]# echo $(( b  +  1   ))    #双小括号的两端有几个空格都无所谓,不限制格式

100

[root@localhost practice]# b=$((b+1))        #将表达式的值赋值给变量

[root@localhost practice]# echo $b

100


7)各种"(())"运算的Shell脚本示例

[root@localhost practice]# cat test.sh 

#!/bin/bash

a=10

b=5

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 practice]# sh test.sh 

a-b=5

a+b=15

a*b=50

a/b=2

a**b=100000

a%b=0




三:let运算命令的用法实践

let运算命令的语法格式为:let赋值表达式

let赋值表达式的功能等同于“((赋值表达式))”

[root@localhost practice]# i=4

[root@localhost practice]# i=i+6

[root@localhost practice]# echo $i

i+6

[root@localhost practice]# unset i

[root@localhost practice]# i=4

[root@localhost practice]# let i=i+6

[root@localhost practice]# echo $i

10

let i=i+6等价于((i=i+6))




四:expr命令的用法实践

 expr命令用法: expr命令既可以用于整数运算,也可以用于相关字符串长度、匹配等的运算处理 

1)expr用于计算

语法:expr Expression

注意:运算符及用于计算的数字左右都至少有一个空格,否则会报错。

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

[root@localhost practice]# expr 2 + 2

4

[root@localhost practice]# expr 2 - 2

0

[root@localhost practice]# expr 2 * 2

expr: syntax error

[root@localhost practice]# expr 2 \* 2    #这个*号需要用\来转义

4

[root@localhost practice]# expr 2 / 2 

1

 

2)expr配合变量计算

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

[root@localhost practice]# i=5

[root@localhost practice]# i=`expr $i + 5`

[root@localhost practice]# echo $i

10


3)expr判断一个变量值或字符串是否为整数

[root@localhost practice]# i=5

[root@localhost practice]# expr $i + 6 &>/dev/null     #把i和整数相加,&>/dev/null表示不保留任何输出

[root@localhost practice]# echo $?                               #输出返回值,返回0,则证明i的值为整数

0

[root@localhost practice]# i=ywxi

[root@localhost practice]# expr $i + 6 &>/dev/null 

[root@localhost practice]# echo $?                              #输出返回值,返回为非0,则证明i的值不为整数

2

结论:利用expr做计算,将一个未知的变量和一个已知的整数相加,看返回值是否为0,如果为0就可以判断出未知变量是整数,否则就不是整数


4)expr match功能进行整数判断

[root@localhost practice]# expr match 1 [0-9][0-9]*$   

1

[root@localhost practice]# expr match 564641 [0-9][0-9]*$        #用正则匹配出符合要求的位数,大于0则为整数

6

[root@localhost practice]# cat exprmatch.sh        #脚本测试

#!/bin/bash

if [[ `expr match "$1" [0-9][0-9]*$` == 0 ]]

then

    echo "$1 is not a num"

else

    echo "$1 is a num"

fi

[root@localhost practice]# sh exprmatch.sh 2        #为整数的输出

2 is a num

[root@localhost practice]# sh exprmatch.sh dsa        #不为整数的输出

dsa is not a num



5)expr特殊用法:判断文件扩展命名是否符合要求

[root@localhost practice]# cat expr5.sh 

#!/bin/bash

if expr "$1" : ".*\.txt" &>/dev/null

then

    echo "you are using $1"

else

    echo "please use *.txt file"

fi

[root@localhost practice]# sh expr5.sh 1

please use *.txt file

[root@localhost practice]# sh expr5.sh 1.txt

you are using 1.txt

[root@localhost practice]# sed -n '10,20p' `which ssh-copy-id`        #expr命令实现系统ssh服务自带的ssh-copy-id公钥分布脚本示例如下

if [ "-i" = "$1" ]; then

  shift

  # check if we have 2 parameters left, if so the first is the new ID file

  if [ -n "$2" ]; then

    if expr "$1" : ".*\.pub" > /dev/null ; then

      ID_FILE="$1"

    else

      ID_FILE="$1.pub"

    fi

    shift         # and this should leave $1 as the target name

  fi


6)通过expr计算字符串的长度

[root@localhost practice]# char="I am ywxi"

[root@localhost practice]# expr length "$char"

9

[root@localhost practice]# echo ${#char}        #常用的计算字符串长度方法

9

[root@localhost practice]# echo ${char}|wc -L

9

[root@localhost practice]# echo ${char}|awk '{print length($0)}'

9




五:bc命令的用法实践

bc是类unix下的计算器,因此,除了可以作为计算机来使用,还可以作为命令行计算工具使用

[root@localhost practice]# bc        #执行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

2*3+5

11

[root@localhost practice]# echo 5+3|bc

8

[root@localhost practice]# echo 5*3+5|bc

20

[root@localhost practice]# echo "scale=2;5/3"|bc        #使用scale=2保留2位小数

1.66

[root@localhost practice]# echo "scale=5;5/3"|bc        #使用scale=5保留5位小数

1.66666


重:多种运算法拓展实践,通过一条命令输出1+2+3+...+10的表达式,并计算出结果。

打印表达式的命令如下:

[root@localhost practice]# seq -s "+" 10

1+2+3+4+5+6+7+8+9+10

[root@localhost practice]# echo {1..10}|tr " " "+"

1+2+3+4+5+6+7+8+9+10

实现本题的多种方法: 

[root@localhost practice]# echo `seq -s "+" 10`=`seq -s "+" 10|bc`        #使用bc计算,bc命令独有特点事除了支持证书运算之外,还支持小数运算

1+2+3+4+5+6+7+8+9+10=55

[root@localhost practice]# echo "`seq -s '+' 10`="$((`seq -s "+" 10`))         #使用"(( ))"计算

1+2+3+4+5+6+7+8+9+10=55

[root@localhost practice]# echo `seq -s '+' 10`=`seq -s " + " 10|xargs expr`        #使用expr计算,注意用于计算的数字左右都至少有一个空格,否则会报错

1+2+3+4+5+6+7+8+9+10=55

[root@localhost practice]# echo `seq -s '+' 10`=$(echo $[`seq -s "+" 10`])         #使用$[ ]计算.

1+2+3+4+5+6+7+8+9+10=55




六:awk实现计算示例

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

[root@localhost practice]# echo "6.6 3.3"|awk '{print ($1-$2)}'

3.3

[root@localhost practice]# echo "6.6 3.3"|awk '{print ($1-2)/$2}'

1.39394

[root@localhost practice]# echo "6.6 3.3"|awk '{print ($1+2)*$2}'

28.38




七:$[ ]符号的运算示例

[root@localhost practice]# i=5

[root@localhost practice]# i=$[i+3]

[root@localhost practice]# echo $i

8

[root@localhost practice]# i=$[i-2]

[root@localhost practice]# echo $i

6

[root@localhost practice]# echo $[2*3]

6

[root@localhost practice]# echo $[2**3]

8

[root@localhost practice]# echo $[2/3] 

0

[root@localhost practice]# echo $[2%3]

2

下面是解决问题的实例:打印杨辉三角

[root@localhost practice]# cat sanjiao.sh 

#!/bin/bash

if (test -z $1) ;then 

     read -p "Input Max Lines:" MAX 

else 

             MAX=$1

fi  

i=1  

while [ $i -le $MAX ]           #i行控制 

do

    j=1  

    while [ $j -le $i ]              #j列控制

    do

        f=$[i-1]        #f=i-1 这是另一种计算写法。  

        g=$[j-1]        #g=j-1 这是另一种计算写法。

        if [ $j -eq $i ] || [ $j -eq 1 ] ; then

            declare SUM_${i}_$j=1           #声明变量 头尾都是1

        else

            declare A=$[SUM_${f}_$j]       #取上一行的j列变量  

            declare B=$[SUM_${f}_$g]       #取上一行的j-1列变量  

            declare SUM_${i}_$j=`expr $A + $B`    #声明并计算当前变量的值  

        fi

        echo -en $[SUM_${i}_$j]" "  #输出当前变量  

        let j++  

    done

    echo   #换行

    let i++

done




八:基于Shell变量输入read命令的运算实践

1)read命令

语法格式:read 【参数】【变量名】

常用参数: -p(prompt) :设置提示信息        -t(timeout):设置输入等待的时间,单位默认为秒

read基本的读入功能示例:

[root@localhost practice]# read -t 5 -p "please input one num:" num        #-t设置等待时间,时间超过就退出了,一般不设置这个值

please input one num:1

[root@localhost practice]# echo $num

1

[root@localhost practice]# read -p "please input two number:" a b            #read的读入功能就相当于交互式接受用户输入,然后给变量赋值,体现了变量赋值灵活

please input two number:2 3

[root@localhost practice]# echo $a

2

[root@localhost practice]# echo $b

3

等价于echo -n "please input two number:" ;read a b


2)read运用于脚本变量读取赋值示例:

脚本1:

[root@localhost practice]# cat 3.sh 

#!/bin/bash

echo -n "Enter your name:"   #参数-n的作用是不换行,echo默认是换行

read  name                   #从键盘输入

echo "hello $name,welcome to my program"     #显示信息

exit 0                       #退出shell程序。

[root@localhost practice]# sh 3.sh 

Enter your name:ywxi

hello ywxi,welcome to my program


脚本2:

#该例子使用了-n选项,后接数值1个,指示read命令只要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键。

[root@localhost practice]# cat 4.sh 

#!/bin/bash

read -n1 -p "Do you want to continue [Y/N]: "  answer

case $answer in

Y | y)

echo -e  "\nfine ,continue";;

N | n)

echo "ok,good bye";;

*)

echo "error choice";;

esac

exit 0

[root@localhost practice]# sh 4.sh 

Do you want to continue [Y/N]: Y

fine ,continue

[root@localhost practice]# sh 4.sh 

Do you want to continue [Y/N]: y

fine ,continue


脚本3:

#最后,还可以使用read命令读取Linux系统上的文件。每次调用read命令都会读取文件中的"一行"文本。当文件没有可读的行时,read命令将以非零状态退出。

#读取文件的关键是如何将文本中的数据传送给read命令。

#最常用的方法是对文件使用cat命令并通过管道将结果直接传送给包含read命令的while命令。

[root@localhost practice]# cat 5.sh 

#!/bin/bash

count=1     #赋值语句,不加空格

cat test | while read line        #cat 命令的输出作为read命令的输入,read读到的值放在line中

do

    echo "Line $count:$line"

    count=$[ $count + 1 ]          #注意中括号中的空格。

done

echo "finish"

exit 0

[root@localhost practice]# cat test

read

test

ywxi

[root@localhost practice]# sh 5.sh 

Line 1:read

Line 2:test

Line 3:ywxi

finish