shell 命令列實現
獲取UNIX型別的選項:
unix有一個優點就是標準UNIX命令在執行時都具有相同的命令列格式:
command -options parameters
如果在執行Shell程式也採用上述格式,Bourne Shell中提供了一條獲取和處理命令列選項的語句,即getopts語句。該語句的格式為:
getopts option_string variable
其中option_string中包含一個有效的單字元選項。若getopts命令在命令列中發現了連字元,那麼它將用連字元後面的字元同 option_string相比較。若有匹配,則把變數variable的值設為該選項。若無匹配,則
有時侯選項中還帶一個值,getopts命令同樣也支援這一功能。這時需要在option_string中選項字母后加一個冒號。當 getopts命令發現冒號後,會從命令列該選項後讀取該值。若該值存在,那麼將被存在一個特殊的變數OPTARG中。如果該值不存在,getopts命令將在OPTARG中存放一個問號,並且在標準錯誤輸出上顯示一條訊息。
optstring option字串,會逐個匹配
varname 每次匹配成功的選項
arg 引數列表,沒寫時它會取命令列引數列表
$OPTIND 特殊變數,option index,會逐個遞增, 初始值為1
$OPTARG 特殊變數,option argument,不同情況下有不同的值
細則1:當optstring以”:“開頭時,getopts會區分invalid option錯誤和miss option argument。invalid option錯誤時,varname會被設成?,$OPTARG是出問題的option;miss option argument時,varname會被設成:(在我的fedora系統裡測試
當optstring不以”:“開頭,invalid option錯誤和miss option argument錯誤都會使varname被設成?,$OPTARG是出問題的option(在我的fedora系統裡測試OPTARG為空).細則2:當optstring中的字母跟”:“時,表明該option可接引數,引數(argument)放在$OPTARG中,如果缺引數,且optstring是以”:“開頭,則varname的值會是:(在我的fedora系統裡測試OPTARG為?),$OPTARG是該option, 否則varname的值是?,$OPTARG是該option.(參照細則1)(在我的fedora系統裡測試OPTARG為空)
1 #!/bin/bash
2 if [[ $# -lt 1 ]];then
3 echo "USAGE:`basename $0` [-a] [-b value] [-c]"
4 exit 1
5 fi
6
7 while getopts :ab:c name
8 do
9 case $name in
10 a) aflag=1
11 echo "a"
12 ;;
13 b) bflag=1
14
15 if [[ ${OPTARG:0:1} = "-" ]]; then
16 echo "invalid parameter of $OPTARG"
17 exit 1
18 fi
19
20 bval=$OPTARG
21 ;;
22 c) cflag=1
23 echo "c"
24 ;;
25 \?) echo "Invalid option :`basename $0` [-a] [-b value] [-c]"
26 exit 1
27 ;;
28 :) echo "$0:Must supply an argument to -$OPTARG."
29 exit 1
30 ;;
31 esac
32 done
33 echo $bval
在getopts分析選項時,如果-b後面不帶引數,直接跟-c的話,那麼-c將作為-b的引數。
下面是一個簡單例子(指令碼為getopt):
#/bin/bash
echo $0
echo $*
while getopts ":a:bc" opt
do
case $opt in
a )
echo $OPTARG
echo $OPTIND;;
b )
echo "b $OPTIND";;
c )
echo "c $OPTIND";;
? )
echo "error"
exit 1;;
esac
done
echo $OPTIND
echo $*
shift $(($OPTIND - 1))
echo $*
echo $0
執行sh getopt.sh -a 12 -b -c 34 -m輸出:
getopt.sh
-a 12 -b -c 34
12
3
b 4
c 5
5
-a 12 -b -c 34
34
getopt.sh
可以得出一些結論:
1、$0在用sh 或者 ./執行指令碼時,指的是指令碼名,用source或.執行時,永運是bash,這也反應了sh 或者 ./執行指令碼的原理和source的方式是不同的.
2、$1 (1....n)指的第一個引數到....第n個引數
3、OPTARG儲存相應選項的引數OPTIND指向的是下一個引數的index
4、shift 會改變引數的順序,通過左移去掉某些引數
5、getopts檢測到非法引數就會停止,比如上例中遇到34就會終止,並不會去檢測-m了,也就是說只要前一個引數是合法的(包含在option_string中的),就會繼續檢測下一個引數。
另外: unset OPTIND 可以解決shell指令碼的函式中使用getopts