Bash腳本之if、case、read和位置參數
在學會了基本的命令之後,我們就可以使用這些命令來進行編程了。在Linux中的編程稱為shell腳本,是將命令進行結合形成的類似Windows中批處理的東西。在這個腳本中,可以有變量和結構體。每一個程序所擁有的程序執行過程,例如:順序執行、選擇執行和循環執行都可以在腳本中體現出來。下面就對shell腳本進行介紹。
首先,shell腳本編程是過程式編程語言,也就是說shell腳本強調接下來要執行的步驟,就好像是人在對shell說接下來要做什麽,要明確的指出每一步的方法。然後shell還是腳本類語言,它不需要編譯,可以直接執行,由解釋器來進行解釋,所以它也是解釋型語言。所以shell腳本是過程式編程語言,采用順序執行結構,以從左到右,從上到下順序執行所有的語句,也就是命令。
shell腳本默認為順序進行執行,但是當我們有需要的時候可以進行跳轉,來實現選擇和循環這兩種執行結構。選擇執行結構使用“if”或“case”命令來實現。其中“if”是根據邏輯判斷的結果進行選擇,“case”是根據可選的取值進行選擇。先說“if”語句:
格式可以為一行就寫完:
if 判斷條件 ; then 命令 ; [ elif 判斷條件 ; then 命令 ; ]... [ else 命令 ; ] fi
如果條件為真,則執行then後的命令,否則,不做任何操作。
if語句還可以寫成多行形式,看起來更加直觀(分號可省略):
if CONDITION #CONDITION為判斷條件,接下來都以英文出現 then STATEMENT #STATEMENT為要執行的語句(命令),接下來都以英文出現 fi
if CONDITION ; then #這種格式也可以 #但是當“then”語句和“if”在同一行的時候需要在他們直接加上分號“;”。 STATEMENT1 STATEMENT2 ... fi
上面的結構為單分支結構,意思就是只有當條件滿足的時候執行,接下來說一說雙分支結構,這個結構中如果條件為真,就執行then後面的命令,否則就執行else後面的命令,也就是不管條件如何,都會有一個命令來執行,而不是當條件不滿足的時候跳過“if”語句。格式如下:
if CONDITION ; then STATEMENT ... else STATEMENT ... fi
比雙分支結構更詳細的是多分支結構,這個結構對條件的描述更加詳細,能夠應對多種情況。首先判斷CONDITION1是否為真,如果為真,則執行第一個then後面的語句;否則就判斷CONDITION2是否為真,如果為真,就執行第二個then後面的語句;否則就判斷CONDITION3是否為真,如果為真,就執行第三個then後面的語句...;如果所有的CONDITION都為假,就執行else後面的語句。格式為:
if CONDITION1 ; then STATEMENT ... elif CONDITION2 ; then STATEMENT ... elif CONDITION3 ; then STATEMENT ... ... else STATEMENT ... fi
接下來就以多分支為結構寫一個腳本,裏頭為以下內容(腳本執行過程參考原先寫的博客:Bash腳本):
#!/bin/bash read -p "輸入一個整數" Get#這句話是為了獲取一個整數 if [ $Get -gt 5 ] ; then#這句話是在獲取到一個整數之後進行判斷(判斷的表達式參考原先寫的博客:shell腳本編程之條件測試——test) echo "這個數大於5" elif [ $Get -lt 5 ] ; then echo "這個數小於5" else echo "這個數等於5" fi
if語句必須以fi結尾
[[email protected] blog]# bash iftest 輸入一個整數3 這個數小於5 [[email protected] blog]# bash iftest 輸入一個整數6 這個數大於5 [[email protected] blog]# bash iftest 輸入一個整數5 這個數等於5
if後既可以跟一個test語句,也可以跟一個命令,如果是命令的話就是判斷這條命令是否執行成功,成功則執行接下來的命令,否則執行“else”,比如:
寫一個腳本,裏頭包含以下內容:
#!/bin/bash if ls test ; then echo "test文件存在" else echo "test文件不存在" fi
然後執行此腳本:
[[email protected] blog]# bash ifcom ls: 無法訪問test: 沒有那個文件或目錄 test文件不存在 #因為在當前目錄下沒有test這個文件或文件夾, #所以“ls test”這個命令會執行失敗 #所以if語句就會執行else中的內容 [[email protected] blog]# touch test [[email protected] blog]# bash ifcom test test文件存在
在這個腳本的執行過程中我們可以發現輸出了很多我們並不需要的內容,所以我們可以對腳本進行如下修改來刪掉這些無用的信息:
#!/bin/bash if ls test&>/dev/null ; then #將if後命令的輸出重定向到“/dev/null”中,這是一種常用的方法 #因為很多的時候我們不需要if後用來進行判斷的命令進行輸出 echo "test文件存在" else echo "test文件不存在" fi
if大概就是這些使用方法了,接下來說一說“case”命令。“case”命令是多分支選擇結構,格式為:
case 詞 in [模式 [| 模式]...) 命令 ;;]... esac
或者寫成有結構的形式:
case 變量 in [模式 [| 模式]...) 命令 ;;] ... esac
模式(PATTERN)可以是:
1.普通的文本字符
2.globbing風格的通配符:
*:任意長度任意字符
?:任意的單個字符
[]:範圍內的任意單個字符
[^]:範圍外的任意單個字符
3.|:或
當匹配到這個模式之後就會執行這個“)”之後的命令,直到遇到兩個連續的分號“;;”為止。例如:
建立一個腳本,然後在腳本中寫入以下內容:
#!/bin/bash read -p "輸入a、b、c中的一個:" Get case $Get in a) echo "輸入的是a" ;; b) echo "輸入的是b" ;; c) echo "輸入的是c" ;; esac
[[email protected] blog]# bash case 輸入a、b、c中的一個:b 輸入的是b
在這個腳本中僅僅只是對相同的字符進行匹配,我們還可以使用模式進行匹配,例如:
建立一個腳本,然後在腳本中寫入以下內容:
#!/bin/bash read -p "輸入一個數字或字母:" Get case $Get in [[:digit:]]) echo "輸入的是一個數字" ;; [[:alpha:]]) echo "輸入的是一個字母" ;; *) echo "輸入的既不是數字,也不是字母" ;; esac
[[email protected] blog]# bash caseMode 輸入一個數字或字母:s 輸入的是一個字母 [[email protected] blog]# bash caseMode 輸入一個數字或字母:1 輸入的是一個數字 [[email protected] blog]# bash caseMode 輸入一個數字或字母:% 輸入的既不是數字,也不是字母
在這個腳本中使用了模式進行匹配,這個模式可以和上一個例子進行組合使用。其中在最後一個選項中用到了“*”這個字符,代表了任意,也就是說當上頭的任何條件都不滿足的時候就執行這個選項。由此來看case要比if更加的方便使用,至少格式要比if看起來清晰。
在上面給出的所有bash腳本中都是使用read命令來進行變量數據的讀入,那麽下面說一說“read”這個命令:
使用格式為:
read [-a 數組] [-p 提示符] [-t 超時] [名稱 ...]
名稱一般為變量名或數組名。如果不寫名稱,則系統會將read讀到的信息保存在REPLY變量中。比如:
[[email protected] blog]# read a 123 [[email protected] blog]# echo $a 123 [[email protected] blog]# read 456 [[email protected] blog]# echo $REPLY 456
“-a”選項是輸入數組
“-p”選項是為了在讀入數據的時候給出提示,等同於在使用read命令之前使用echo命令輸出一句不換行的文字,比如:
[[email protected] blog]# read -p "輸入:" 輸入:123 [[email protected] blog]# echo -n "輸入:" ; read #分號“;”是同時執行多個命令(具體參考原先寫的博客——多命令執行) 輸入:123
“-t”選項是等待一段時間,在這段時間內如果沒有輸入,就跳過read命令執行接下來的命令。這個命令實現了Linux的哲學思想,就是盡量不與用戶進行交互,實現自動化處理。不過在使用這個選項的時候需要註意:一旦使用-t選項定義了超時時間,我們必須在後面判斷給定的變量是否為空,如果為空需要為變量提供默認值
“-s”選項是關閉回顯,這個選項在輸入的時候不會顯示輸入的內容
以上是read的一些常見的用法和選項,但是這些都是在腳本開始運行之後進行的賦值,我們還可以在腳本運行之前就進行賦值。也就是在腳本執行的時候將腳本內可能會用到的變量傳進去。在腳本中存在著位置參數變量:$1, $2, $3, ...這些變量是可以在shell腳本中直接進行引用的,不同的數字分別對應著腳本執行時腳本名後頭跟著的第幾個參數,這些參數使用空格隔開。在編寫shell腳本的時候直接使用$1...進行調用,比如:
建立一個腳本,然後在腳本中寫入以下內容:
#!/bin/bash echo "第一個參數是$1" echo "第二個參數是$2" echo "第三個參數是$3"
[[email protected] blog]# bash bianliang a b c 第一個參數是a 第二個參數是b 第三個參數是c
在使用位置參數的時候可以配合shift [n]命令,這個命令的功能是將位置參數左移,命令後頭跟一個數字作為參數,如果沒有,默認為1,在執行命令之後會將位置參數左移給出的數字那麽多位,這麽說可能沒有看懂,那麽舉個例子:
在腳本中寫入以下內容:
#!/bin/bash echo \$1:$1 shift echo \$1:$1
[[email protected] blog]# bash shift a b $1:a $1:b
在這個腳本中我們為第一個位置參數$1賦的值為“a”,在第一行輸出的就是a,經過第二行的命令“shift”將位置參數中的內容左移默認的一位之後再輸出$1,就變成了原先的第二個參數“b”
除了使用數字來引用的位置參數,還有一些使用特殊符號來引用的具有特殊功能的變量:
$#:所有的位置參數的總數;
$*:給出的所有位置參數的列表;當使用雙引號引用時,整個參數列表被當做一個字符串;
$@:給出的所有位置參數的列表;當時有雙引號引用時,每個參數作為單獨的字符串存在;
$0:所執行的腳本文件自身的路徑(當前這個被執行的腳本的名字);
比如:
更改上一個腳本,改為以下內容:
#!/bin/bash echo "\$#:$#" echo "\$*:$*"++ echo "\$@:$@" echo "\$0:$0"
[[email protected] blog]# bash bianliang a b c $#:3 $*:a b c $@:a b c $0:bianliang
Bash腳本之if、case、read和位置參數