玩轉Bash腳本:選擇結構之case
總第5篇
之前,我們談到了if。
這次我們來談還有一種選擇結構——case。
case與if
if用於選擇的條件,不是非常多的情況,假設選擇的條件太多。一系列的if。elif,。也是醉了。
沒錯,case在bash中的地位,和switch在C中的地位一樣。
可是使用方法可大有不同。
代碼塊
不論什麽語言都有代碼塊的概念,C語言中的花括號{ },python中的冒號和縮進。bash中的代碼塊風格不是非常統一。可是在選擇結構中是同樣的——反語。if結構使用if...fi標識一個代碼塊的作用域,而case也是用case...esac表示塊作用域的。。
基本結構
看樣例echo.sh:
#!/bin/bash str="is good " read -p "你喜歡什麽顏色:" color case $color in red) echo -e "\e[1;31m$color $str \e[0m";; green) echo -e "\e[1;32m$color $str \e[0m";; yellow) echo -e "\e[1;33m$color $str \e[0m";; blue) echo -e "\e[1;34m$color $str \e[0m";; *) echo -e "\e[1;30m這是什麽顏色?\e[0m";; esac
把變量color的值,依次和以下右括號中的值做比較。假設同樣,就運行後面的語句。
來執行一下
兩個分號;;
註意每一個條件末尾都是兩個分號。
這非常好理解。就像C語言的switch裏面每一個case都常常會有一個break一樣。由於每一個條件滿足的時候,須要運行的語句可能不止一句。而在bash中多個語句在一行是用一個分號間隔的。這樣兩個分號就表示著語句結束。另外加一個空語句,也就是說要運行的語句都完畢了。
與c語言的switch不同的是,c語言中每一個條件(case語句)後面不一定都要有break。假設沒有break,則繼續運行以下的條件的語句。假設你想像c語言那樣多個條件共用一套語句,怎麽辦呢?
請繼續閱讀。
分號扭號;&
所謂扭號,就是And符號——&,我認為叫扭號更簡潔。。看一段C代碼:
#include<stdio.h> int main(){ char ans; printf("你喜歡編程麽:"); scanf("%c",&ans); switch(ans){ case 'y': case 'Y':printf("我也是\n");break; case 'n': case 'N':printf("sorry,跟你沒什麽好談的\n");break; } }也就是說。在C中,case後面假設不加break,那麽在運行完匹配的語句後,將接著運行。而無論以下的條件匹配不匹配,直到遇到break為止。這種語法。十分靈活。那麽bash中又怎樣實現呢?難道在末尾加一個分號?錯錯錯。答案是一個分號加一個扭號。
#!/bin/bash read -p "你喜歡編程麽:(y/n):" ans case $ans in y);& Y) echo "我也是";; n);& N) echo "sorry,跟你沒什麽好談的";; esac
分號分號扭號;;&
除了 ;&結束語句以外。另一種是 ;;& 來結束語句的使用方法。
可是意義有所不同,;;&的使用方法是使得條件越來越精確。
#!/bin/bash read -p "請輸入一個區號:" num case $num in *)echo -n "中國";;& 03*)echo -n "河北省";;& ??10)echo "邯鄲市";; ?
?
11)echo "石家莊";; ??17)echo "滄州市";; 07*)echo -n "江西省";;& ??91)echo "南昌市";; ??92)echo "九江市";; ?
?97)echo "贛州市";; esac
關於通配符*和?,我們以下會講到。這裏,你僅僅須要知道。條件語句以 ;;& 結束的時候,程序運行到這裏不會停止,會繼續測試以下條件。假設滿足繼續運行,直到遇到 ;; 或esac
註意。以上這兩種扭號的使用方法,是bash自己的 特性,對於其它shell,並不支持。
假設考慮移植性,就不要這樣寫了。
只用正規的兩個分號就能夠了。
右括號裏的模式
基本正則
)右括號。類似c語言中switch中的case。然而與之不同的是。Bash中的右括號中面,不僅支持完整的字符串(c語言中僅僅支持整型數據。包含int和char
,不支持字符串)還支持“模式”匹配。模式的概念,假設了解正則表達式。那麽就非常easy理解了。只是case語句中與正則表達式略有不同。貌似支持的並不完整。
- *是匹配0個或多個不論什麽字符。
- ?是匹配一個字符。
能夠看做一個占位符。
- [ ]表示一個範圍。
- ( )枚舉字符串。可是須要轉義
#!/bin/bash read -p "請輸入一個數字:" num case $num in 2*)echo "匹配2*";;& 2?方括號表示範圍,你能夠使用[123]來匹配1或2或3。而不是123。也能夠使用[0-9]、[a-zA-Z]這種寫法。熟悉正則的同學。這些都不是問題。)echo "匹配2?";;& [0-9])echo "匹配[0-9]";; esac
註意我上面用到了 ;;& 也就是說在匹配了一個模式之後,不會停止,還會繼續向下運行。
運行效果:
枚舉字符串
一般的寫法比方(123|456|789)匹配123,456,789這三個數。
可是由於case中右括號有特殊含義,所以進行了轉義。
然後我的寫法就是(123|456|789\)。可是這樣有個問題就是789無法得到匹配。123和456倒是能夠。我也是不明所以(見笑,知情者望告知)。
於是我又改了一版,最終匹配全然——(123|456|789|\)。
如今加上一句到剛才的腳本中——(123|456|789 \))echo "匹配(123|456|789|\)";;&
POSIX字符類
一般的編程語言中的正則表達式。支持\w,\d這類的字符類(Character Classes)。而Unix-like系統上。支持的字符類是POSIX風格的。
見下表
類 |
描 述 |
擴 展 |
[:alnum:] |
字母和數字字符 |
[0-9a-zA-Z] |
[:alpha:] |
(letters)字母字符(字母) |
[a-zA-Z] |
[:ascii:] |
7位ASCII |
[\x01-\x7F] |
[:blank:] |
水平空白符(空格、制表符) |
[ \t] |
[:cntrl:] |
控制字符 |
[\x01-\x1F] |
[:digit:] |
數字 |
[0-9] |
[:graph:] |
用墨水打印的字符(非空格、非控制字符) |
[^\x01-\x20] |
[:lower:] |
小寫字母 |
[a-z] |
[:print:] |
可打印字符(圖形類加空格和制表符) |
[\t\x20-\xFF] |
[:punct:] |
隨意標點符號,如句點(.)和分號(;) |
[-!"#$%&‘( )*+,./:;<=>?@[\\\]^_‘{|}~] |
[:space:] |
空白(換行、回車、制表符、空格、垂直制表符) |
[\n\r\t \x0B] |
[:upper:] |
大寫字母 |
[A-Z] |
[:xdigit:] |
十六進制數字 |
[0-9a-fA-F] |
實際使用的時候,還要在這些字符類的方括號外面。再套一層方括號才行。
#!/bin/bash read -p "請隨意輸入,能夠包括空格等空白符" ch #echo $ch case $ch in *[[:lower:]]*)echo lower;;& *[[:upper:]]*)echo upper;;& *[[:digit:]]*)echo digit;;& *[[:punct:]]*)echo punct;;& *[[:ascii:]]*)echo ascii;;& *[[:cntrl:]]*)echo cntrl;;& *[[:print:]]*)echo print;;& *[[:space:]]*)echo space;;& *[[:xdigit:]]*)echo xdigit;;& *[[:graph:]]*)echo graph;;& *[[:blank:]]*)echo blank;;& *[[:alnum:]]*)echo alnum;;& *[[:alpha:]]*)echo alpha;;& esac
這個腳本。大家自己去測試吧。當然了有些字符(比方控制字符)貌似不好輸入。
這樣不好測試[:cntrl:]這個字符類,這裏我告訴您一下,ascii碼中27相應的控制字符就是ESC。
測試腳本的時候,能夠按一下ESC鍵。或者鍵入^[字符,也是一樣的。
本系列(玩轉Bash腳本)很多其它文章,請訪問:http://blog.csdn.net/column/details/wanbash.html
玩轉Bash腳本:選擇結構之case