1. 程式人生 > >shell 命令列實現

shell 命令列實現

獲取UNIX型別的選項:

  unix有一個優點就是標準UNIX命令在執行時都具有相同的命令列格式:

command -options parameters

  如果在執行Shell程式也採用上述格式,Bourne Shell中提供了一條獲取和處理命令列選項的語句,即getopts語句。該語句的格式為:

getopts option_string variable

  其中option_string中包含一個有效的單字元選項。若getopts命令在命令列中發現了連字元,那麼它將用連字元後面的字元同 option_string相比較。若有匹配,則把變數variable的值設為該選項。若無匹配,則

variable設為?。當getopts發現連字元後面沒有字元,會返回一個非零的狀態值。Shell程式中可以利用getopts的返回值建立一個迴圈。

  有時侯選項中還帶一個值,getopts命令同樣也支援這一功能。這時需要在option_string中選項字母后加一個冒號。當 getopts命令發現冒號後,會從命令列該選項後讀取該值。若該值存在,那麼將被存在一個特殊的變數OPTARG中。如果該值不存在,getopts命令將在OPTARG中存放一個問號,並且在標準錯誤輸出上顯示一條訊息。

  optstring  option字串,會逐個匹配

  varname     每次匹配成功的選項

  arg             引數列表,沒寫時它會取命令列引數列表

  $OPTIND     特殊變數,option index,會逐個遞增初始值為1

  $OPTARG    特殊變數,option argument,不同情況下有不同的值

細則1optstring”:“開頭時,getopts會區分invalid option錯誤和miss option argumentinvalid option錯誤時,varname會被設成?,$OPTARG是出問題的optionmiss option argument,varname會被設成:(在我的fedora系統裡測試

OPTARG?),$OPTARG是出問題的option.

optstring不以”:“開頭,invalid option錯誤和miss option argument錯誤都會使varname被設成?,$OPTARG是出問題的option(在我的fedora系統裡測試OPTARG為空).細則2optstring中的字母跟”:“,表明該option可接引數,引數(argument)放在$OPTARG,如果缺引數,optstring是以”:“開頭,varname的值會是:(在我的fedora系統裡測試OPTARG?),$OPTARG是該option, 否則varname的值是?,$OPTARG是該option.(參照細則1)(在我的fedora系統裡測試OPTARG為空)

#!/bin/bash  

if [[ $# -lt 1 ]];then  

    echo "USAGE:`basename $0` [-a] [-b value] [-c]"  

    exit 1  

fi    

while getopts :ab:c name  

do  

    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個引數

3OPTARG儲存相應選項的引數OPTIND指向的是下一個引數的index

4shift 會改變引數的順序,通過左移去掉某些引數

5getopts檢測到非法引數就會停止,比如上例中遇到34就會終止,並不會去檢測-m了,也就是說只要前一個引數是合法的(包含在option_string中的),就會繼續檢測下一個引數。

另外: unset OPTIND  可以解決shell指令碼的函式中使用getopts