五、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 \n"
????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
?
?
?
轉載于:https://www.cnblogs.com/zhongguiyao/p/8983262.html
總結
- 上一篇: 【来龙去脉系列】.net分布式系统架构的
- 下一篇: caffe的python接口学习(2)生