1、for/do/done
Shell指令碼的for
迴圈結構和C語言很不一樣,它類似於某些程式設計語言的foreach
迴圈。例如:
#! /bin/shfor FRUIT in apple banana pear; do echo "I like $FRUIT"done
FRUIT
是一個迴圈變數,第一次迴圈$FRUIT
的取值是apple
,第二次取值是banana
,第三次取值是pear
。再比如,要將目前的目錄下的chap0
、chap1
、chap2
等檔案名稱改為chap0~
、chap1~
、chap2~
等(按慣例,末尾有~字元的檔案名稱表示臨時檔案),這個命令可以這樣寫:
$ for FILENAME in chap?; do mv $FILENAME $FILENAME~; done
也可以這樣寫:
$ for FILENAME in `ls chap?`; do mv $FILENAME $FILENAME~; done
2、 while/do/done
while
的用法和C語言類似。比如一個驗證密碼的指令碼:
#! /bin/shecho "Enter password:"read TRYwhile [ "$TRY" != "secret" ]; do echo "Sorry, try again" read TRYdone
下面的例子通過算術運算控制迴圈的次數:
#! /bin/shCOUNTER=1while [ "$COUNTER" -lt 10 ]; do echo "Here we go again" COUNTER=$(($COUNTER+1))done
Shell還有until迴圈,類似C語言的do...while迴圈。本章從略。
3、 位置參數和特殊變數
有很多特殊變數是被Shell自動賦值的,我們已經遇到了$?
和$1
,現在總結一下:
常用的位置參數和特殊變數
$0 |
相當於C語言main 函數的argv[0] |
$1 、$2 ... |
這些稱為位置參數(Positional Parameter),相當於C語言main 函數的argv[1] 、argv[2] ... |
$# |
相當於C語言main 函數的argc - 1 ,注意這裡的# 後面不表示注釋 |
$@ |
表示參數列表"$1" "$2" ... ,例如可以用在for 迴圈中的in 後面。 |
$? |
上一條命令的Exit Status |
$$ |
當前Shell的進程號 |
位置參數可以用shift
命令左移。比如shift 3
表示原來的$4
現在變成$1
,原來的$5
現在變成$2
等等,原來的$1
、$2
、$3
丟棄,$0
不移動。不帶參數的shift
命令相當於shift 1
。例如:
#! /bin/shecho "The program $0 is now running"echo "The first parameter is $1"echo "The second parameter is $2"echo "The parameter list is $@"shiftecho "The first parameter is $1"echo "The second parameter is $2"echo "The parameter list is $@"
4、函數
和C語言類似,Shell中也有函數的概念,但是函數定義中沒有傳回值也沒有參數列表。例如:
#! /bin/shfoo(){ echo "Function foo is called";}echo "-=start=-"fooecho "-=end=-"
注意函數體的左花括弧{和後面的命令之間必須有空格或換行,如果將最後一條命令和右花括弧}
寫在同一行,命令末尾必須有;號。
在定義foo()
函數時並不執行函數體中的命令,就像定義變數一樣,只是給foo
這個名字一個定義,到後面調用foo
函數的時候(注意Shell中的函數調用不寫括弧)才執行函數體中的命令。Shell指令碼中的函數必須先定義後調用,一般把函數定義都寫在指令碼的前面,把函數調用和其它命令寫在指令碼的最後(類似C語言中的main
函數,這才是整個指令碼實際開始執行命令的地方)。
Shell函數沒有參數列表並不表示不能傳參數,事實上,函數就像是迷你指令碼,調用函數時可以傳任意個參數,在函數內同樣是用$0
、$1
、$2
等變數來提取參數,函數中的位置參數相當於函數的局部變數,改變這些變數並不會影響函數外面的$0
、$1
、$2
等變數。函數中可以用return
命令返回,如果return
後面跟一個數字則表示函數的Exit Status。
下面這個指令碼可以一次建立多個目錄,各目錄名通過命令列參數傳入,指令碼逐個測試各目錄是否存在,如果目錄不存在,首先列印資訊然後試著建立該目錄。
#! /bin/shis_directory(){ DIR_NAME=$1 if [ ! -d $DIR_NAME ]; then return 1 else return 0 fi}for DIR in "$@"; do if is_directory "$DIR" then : else echo "$DIR doesn't exist. Creating it now..." mkdir $DIR > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Cannot create directory $DIR" exit 1 fi fidone
注意is_directory()
返回0表示真返回1表示假。