Linux基礎之bash腳本編程初級-邏輯運算與測試

引言node

前面介紹了bash編程的基礎變量與算術表達式,本文介紹在腳本中的進階知識:測試正則表達式

在bash中測試大致分兩部分:條件測試、組合測試shell

而條件測試又分:數值測試字符串測試文件測試編程

組合測試則有兩種表達方式。具體是什麼表達方式在文章中會有具體展現。bash

                                                       本文實驗環境爲CentOS7.2框架




Linux中爲何要學習測試(判斷)?

ide

當我第一次學習這部份內容時,以爲好難,好不爽。但是這又是想要繼續學習Linux必需要掌握的知識點。爲何?咱們在生活中面對各類選擇時總要問問本身,我是否應該怎樣,不這樣會發生什麼,在生活中就有諸多相似的「測試」,工做中也離不開,而咱們學習Linux掌握這門技術是爲了更好的工做,Linux的學習天然也離不開「測試」。固然這麼說還有些抽象,那麼就舉個具體的例子:接受一個主機的IPv4地址作爲參數,測試是否可連通。若是能ping通,則提示用戶「該IP地址可訪問」;若是不可ping通,則提示用戶「該IP地址不可訪問」。學習

若是你沒有學過測試那麼此時別人讓你寫這麼一個腳本供他使用,你怎麼辦?測試




在正式介紹測試前,咱們須要先介紹下在測試中必備的數學知識:邏輯運算
ui

邏輯運算

邏輯運算在希臘時期就已經出現,不過它正式被運用於數字電路及計算機則是20世紀的一我的物:香農在其碩士論文中提出將布爾代數應用於電子領域的概念,並給出可以構建任何邏輯和數值關係的邏輯電路的解決方法。有了香農的貢獻纔有了現在的計算機。


邏輯運算主要包括三種:與或非,以後在這三種基礎上又出現了異或(這裏再也不介紹)。

在Linux中與或非的運算符號爲:

    : &&     在測試命令中有時也會用-a表示與

    : ||     在測試命令中有時也會用-o表示或

    : !

    與、或、非運算:

    與運算: 1 && 1 = 1      1 && 0 = 0 

    或運算: 1 || 1 = 1      1 || 0 = 1        0 || 1 = 1         0 || 0 = 0

    非運算:  ! 1 = 0        ! 0 = 1

在計算機中因爲用1表示真,0表示假,故上面的三種運算也能夠看作以下概念:

    與運算: 真 && 真 = 真   真 && 假 = 假 

    或運算: 真 || 真 = 真   真 || 假 = 真     假 || 真 = 真      假 || 假 = 假

    非運算:  ! 真 = 假        ! 假 = 真


在測試中經常使用的邏輯運算中的定律

德摩根定律

非(P 且 Q)=(非 P)或(非 Q)

非(P 或 Q)=(非 P)且(非 Q)

它在測試中的做用:一般爲了化簡邏輯表達式

好比在一個測試表達式中出現了多個-a或-o使用德摩根定律能夠減小其個數

! a == b -a ! c == d -a ! d == a 等價於!( a == b -o c == d -o d == a )

當前面-not或!不少時可使用這種表示方式,這兩種是等價的




測試表達式

測試表達式分三種:

一、test EXPRESSION

二、[ EXPRESSION ]

三、` EXPRESSION ` 

上面三種使用各有其適用範圍,限於所學有限沒有能力對其進行一一概括,我以爲剛開始學不須要求全責備,先掌握大致知識框架比較好。以後在實際中遇到再慢慢進行總結。腳本寫的多,遇到的問題多,這三種的使用場景天然就心照不宣了。




條件測試數值測試字符串傳測試文件測試


數值測試:判斷兩個數值的大小及是否相等,有以下

    -gt:是否大於      大於爲真,不然爲假

    -ge:是否大於等於  大於等於爲真,不然爲假

    -eq:是否等於      等於爲真,不然爲假

    -ne:是否不等於    不等於爲真,不然爲假

    -lt:是否小於      小於爲真,不然爲假

    -le:是否小於等於  小於等於爲真,不然爲假


下面是一個小例子顯示其簡單用法,$?執行狀態返回值,能夠查看上一條命令執行結果的真與假,0表示爲真1-255爲假

[root@localhost test]# [ 1 -eq 2 ]
[root@localhost test]# echo $?
1

咱們判斷1是否等於2,狀態返回值爲1判斷執行結果爲假,因此1不等於2.

………………………………………………………………………………………………………………………

字符串測試:判斷字符串是否符合或等於給定的字符串

字符串的判斷大小是依據ASCII中字符對應的數字大小進行

    ==:是否等於     等於爲真,不然爲假 

    >:是否大於      大於爲真,不然爲假

    <:是否小於      小於爲真,不然爲假

    !=:是否不等於  不等於爲真,不然爲假

    =~:左側字符串是否可以被右側的PATTERN(正則表達式)所匹配  若匹配則爲真,不然爲假

    -z 「string」 : 測試字符串是否爲空,空則爲真,不然爲假

    -n 「string」 :測試字符串是否不爲空,不空爲真,不然爲假


下面也舉一個簡單的例子展現字符串測試用法

[root@localhost test]# [ a == b ]
[root@localhost test]# echo $?
1
[root@localhost test]# [ a < b ]   
-bash: b: 沒有那個文件或目錄
[root@localhost test]# [ "a" < "b" ]
-bash: b: 沒有那個文件或目錄
[root@localhost test]# [[ "a" < "b" ]]
[root@localhost test]# echo $?
0

這裏我先對ab是否相等進行判斷,以後查看結果是假,也就是a不是b。以後對其進行大小判斷,而後報錯,先爲ab加""結果報錯,以後又加了[]才未報錯。這裏咱們能夠看到在字符串測試中使用` `方式進行會比較靠譜,但也不必定。用[]仍是` `就是在這種測試中摸索出來的。

下面再對字符是否爲空舉一個例子

[root@localhost test]# name1=
[root@localhost test]# [ -z $name1 ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -n $name1 ] 
[root@localhost test]# echo $?
0

怎麼會出現這種狀況?字符測試爲空居然不靈!別慌,上面咱們曾有經驗,字符測試若是單中括號失敗那就試試雙中括號

[root@localhost test]# [[ -z $name1 ]]
[root@localhost test]# echo $?
0
[root@localhost test]# [[ -n $name1 ]] 
[root@localhost test]# echo $?
1

結果終於如願,上面的兩個例子告訴咱們,當測試結果並非對時,調整下中括號每每有奇效。

………………………………………………………………………………………………………………………

文件測試


一、存在性測試

    -a FILE (少用)

    -e FILE 文件存在性測試,存在爲真,不然爲假

[root@localhost test]# [ -e /etc/fstab ]
[root@localhost test]# echo $?
0
[root@localhost test]# [[ -e /etc/ftab ]]
[root@localhost test]# echo $?
1


二、存在性及類別測試

    -b FILE:是否存在且爲塊設備文件,存在爲真不然爲假

    -c FILE:是否存在且爲字符設備文件,存在爲真,不然爲假

    -f FILE:是否存在且爲普通文件,存在爲真,不然爲假

    -d FILE:是否存在且爲目錄文件,存在爲真,不然爲假

    -h FILE 或 -L FILE :是否存在且爲連接文件,存在爲真,不然爲假

    -p FILE:是否存在且爲命名管道文件,存在爲真,不然爲假

    -S FILE:是否存在且爲套接字文件,存在爲真,不然爲假

[root@localhost test]# [ -f /test/if1 ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -f /test/ ]   
[root@localhost test]# echo $?
1


三、文件權限測試

    -r FILE:是否存在且對當前用戶可讀,存在爲真,不然爲假

    -w FILE:是否存在且對當前用戶可寫,存在爲真,不然爲假

    -x FILE:是否存在且對當前用戶可執行,存在爲真,不然爲假

[root@localhost test]# echo $USER
root
[root@localhost test]# [ -r /test/ ]
[root@localhost test]# echo $?
0


四、文件特殊權限測試


    -g FILE:是否存在且擁有sgid,存在爲真,不然爲假

    -u FILE:是否存在且擁有suid,存在爲真,不然爲假

    -k FILE:是否存在且擁有sticky,存在爲真,不然爲假

[root@localhost test]# [ -g /test/if1 ]
[root@localhost test]# echo $?
1
[root@localhost test]# ll /test/if1 
-rwxr-xr-x. 1 root root 149 8月  15 10:34 /test/if1


五、文件大小測試

    -s FILE:是否存在且非空,存在爲真,不然爲假

[root@localhost test]# [ -s /test/file1 ]
[root@localhost test]# echo $?
1
[root@localhost test]# echo > file1 
[root@localhost test]# [ -s /test/file1 ]
[root@localhost test]# echo $?
0


六、文件時間戳測試

    -N FILE:文件自上一次被讀取以後是否被修改過,被修改過爲真,不然爲假

選取剛剛被修改過得file1測試

[root@localhost test]# [ -N /test/file1 ] 
[root@localhost test]# echo $?
0


七、文件從屬關係測試

    -O FILE:當前用戶是否爲文件的屬主,是爲真,否爲假

    -G FILE:當前用戶是否屬於文件的屬組,是爲真,否爲假

[root@localhost test]# [ -O /test/if1 ]
[root@localhost test]# echo $?
0
[root@localhost test]# ll /test/if1 
-rwxr-xr-x. 1 root root 149 8月  15 10:34 /test/if1


八、雙目測試

    FILE1 -ef FILE2 :FILE1與FILE2是否指向同一個文件系統的相同inode的硬連接,是則爲真,否爲假

    FILE1 -nt FILE2 :FILE1的mtime是否新於FILE2,是爲真,否爲假

    FILE1 -ot FILE2 :FILE1的mtime是否舊於FILE2,是爲真,否爲假

[root@localhost test]# [ /test/if1 -nt /test/file1 ]
[root@localhost test]# echo $?
1

由於file1剛剛被修改過,因此它比if1文件的mtine要新,由於使用-nt故測試結果爲假




組合測試


第一種方式


與  COMMAND1 && COMMAND2   第一條命令爲假後再也不執行第二條命令,爲真方執行。

或  COMMAND1 || COMMAND2   第一條命令爲真後再也不執行第二條命令,爲假方執行。

非  ! COMMAND              對命令結果的真假取反


第二種方式

EXPRESSION -a EXPRESSION  第一條命令爲假後再也不執行第二條命令,爲真方執行。

EXPRESSION -o EXPRESSION  第一條命令爲真後再也不執行第二條命令,爲假方執行。

! EXPRESSION              對命令結果的真假取反


示例:比較1是否比2小若其爲真則進而比較字符name是否等於Name

第一種表達方式

[root@localhost test]# [[ 1 -lt 2 ]] && [[ name == Name ]]

第二種表達方式

[root@localhost test]# [[ 1 -lt 2 -a name == Name ]]    
-bash: 條件表達式中有語法錯誤
-bash: `-a' 附近有語法錯誤
[root@localhost test]# [ 1 -lt 2 -a name == Name ]

用[]仍是` `有時真的須要一遍遍的測試





腳本實踐


簡要介紹下腳本相關內容

shell腳本也屬於一種語言,這種語言屬於弱類型,不須要聲明數據的存儲格式,bash中均當作字符處理,它靠解釋器運行

寫腳本前須要在所打開文件第一行頂格給出shebang,解釋器路徑對於bash就是#!/bin/bash

運行腳本

一、賦予執行權限,並直接運行此程序文件常見格式爲:./文件名

二、直接運行解釋器,將腳本以命令參數傳遞給解釋器程序:bash <腳本文件>


腳本實例


一、寫一個腳本/root/bin/argsnum.sh,接受一個文件路徑做爲參數;若是參數個數小於1,則提示用戶「至少應該給一個參數」,並當即退出;若是參數個數不小於1,則顯示第一個參數所指向的文件中的空白行數

[root@localhost test]# cat scrip1 
#!/bin/bash
#
[ $# -lt 1 ] && echo "At least provide one path" && exit 1
lines_space=`grep '^$' $1 | wc -l`
[ $# -eq 1 ] && echo "The space lines of the first file are :$lines_space"
[ $# -gt 1 ] && echo "None message" && exit 2 

[root@localhost test]# chmod +x scrip1 
[root@localhost test]# ./scrip1 /etc/fstab 
The space lines of the first file are :1
[root@localhost test]# ./scrip1 /etc/fstab /etc
None message
[root@localhost test]# ./scrip1 
At least provide one path

腳本中用到了特殊變量$#位置變量$1數值測試組合測試變量引用


二、寫一個腳本/root/bin/hostping.sh,接受一個主機的IPv4地址作爲參數,先判斷是否合格IP,否,提示IP格式不合法並退出,是,測試是否可連通。若是能ping通,則提示用戶「該IP地址可訪問」;若是不可ping通,則提示用戶「該IP地址不可訪問」

[root@localhost test]# cat scrip2
#!/bin/bash
#
[ $# -lt 1 ] && echo "please give one IP address" && exit 1
[ $# -gt 1 ] && echo "this script just match one IP address" && exit 2
[ $# -eq 1 ] && [[ $1 =~ (([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])\.){3}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4]) ]] && ping -c 1 $1 | sed -n '2p'|grep -o '^64' >> /dev/null && echo "該IP地址可訪問" || echo "該IP地址不可訪問"

[root@localhost test]# chmod +x scrip2
[root@localhost test]# ./scrip2
please give one IP address
[root@localhost test]# ./scrip2 192.168.1.1
該IP地址不可訪問
[root@localhost test]# ./scrip2 192.168.85.3
該IP地址可訪問
[root@localhost test]# ./scrip2 192.168.85.3 192.168.168.1
this script just match one IP address

上面思路,先判斷參數個數,也就是是否在腳本後加IP。而後判斷IP是否符合規範,以後進行若IP可ping通給出相應提示,這個腳本的大體思路就是這樣。



關於腳本的我的感覺

寫腳本前先要理清楚思路,這個問題要怎麼解決,對哪些內容要進行測試,都須要用到哪些測試方法,須要設置哪些變量,用到哪些組合測試...

上述肯定後就開始寫,寫完再進行調試。不少時候就算本身想的都沒錯,但是腳本寫完依舊不能成功執行或達成想要的結果,由於初學總會出現各類意料不到的狀況好比[]與` `的錯誤使用,好比命令引用忘記加``等等細節。

相關文章
相關標籤/搜索