getopts的使用


getopts的使用
語法格式:getopts [option[:]] [DESCPRITION] VARIABLE
option:表示為某個腳本可以使用的選項
":":如果某個選項(option)后面出現了冒號(":"),則表示這個選項后面可以接參數(即一段描述信息DESCPRITION)
VARIABLE:表示將某個選項保存在變量VARIABLE中
 
getopts是linux系統中的一個內置變量,一般用在循環中。每當執行循環是,getopts都會檢查下一個命令選項,如果這些選項出現在option中,則表示是合法選項,否則不是合法選項。並將這些合法選項保存在VARIABLE這個變量中。
getopts還包含兩個內置變量,及OPTARG和OPTIND
OPTARG就是將選項后面的參數(或者描述信息DESCPRITION)保存在這個變量當中。
OPTIND:這個表示命令行的下一個選項或參數的索引(文件名不算選項或參數)
#!/bin/bashwhile getopts ':b:d:' OPT &> /dev/null;do
        case $OPT in
        b)
                echo "The options is b"
                echo $OPTARG ;;
        d)
                echo "The options is d"
                echo $OPTARG ;;
        *)
                echo "Wrong Options"
                exit 7 ;;
        esac
#       echo $OPT
#       echo $OPTARG
done
echo $OPTIND
shift $[$OPTIND-1]
echo $1
 
###執行腳本時,顯示的結果如下###
[root@localhost scriptTEAM]# ./test -d 'nice' fixnale
The options is d  
nice
3
fixnale
###顯示信息說明如下###
當輸入-d時,$OPT=d,$OPTARG='nice',因此就會顯示d)...這一部分的信息。
由於這里有一個選項(-d)和一個參數('nice'),$OPTIND指向命令行中下一個選項或參數的索引位置,因此這里即為3。
shift $[$OPTIND-1]表示將文件名前面的選項和參數踢掉

getopts參數的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost ~] # cat getopts.sh
#!/bin/bash
echo  $*
while  getopts  ":a:bc:"  opt
do
     case  $opt  in
         a)
         echo  $OPTARG $OPTIND;;
         b)
         echo  "b $OPTIND" ;;
         c)
         echo  "c $OPTIND" ;;
         ?)
         echo  "error"
         exit  1;;
     esac
done
echo  $OPTIND
shift  $(( $OPTIND-1 ))
echo  $0
echo  $*

執行結果如下:

1
2
3
4
5
6
7
[root@localhost ~] # sh getopts.sh -a 11 -b -c 6
-a 11 -b -c 6
11 3
b 4
c 6
6
getopts .sh

為什么會得到上面的結果呢?

while getopts ":a:bc:" opt #第一個冒號表示忽略錯誤;字符后面的冒號表示該選項必須有自己的參數。

$optarg 存儲相應選項的參數,如上例中的11、6;

$optind 總是存儲原始$*中下一個要處理的選項(不是參數,而是選項,此處指的是a,b,c這三個選項,而不是那些數字,當然數字也是會占有位置的)位置。

optind初值為1,遇到"x",選項不帶參數,optind+=1;遇到"x:",帶參數的選項,optarg=argv[optind+1],optind+=2;遇到"x::",可選參數,屬於#1和#2之一(轉載過來的,這句我也看不懂)

第一行輸出echo $*

第二行,optind初值為1,選項-a的參數為11,下一個要處理的選項-b位置為3,所以輸出:11 3;

第三行,然后-b要處理的下一個選項-c位置為4,所以輸出:b 4;

第四行,再者-c有參數,所以下一個要處理的位置+2,所以輸出:c 6;

自己隨手輸入的例子:

1
2
3
4
5
6
7
8
[root@localhost ~] # sh getopts.sh -a 11 -b -b 9 -c 6
-a 11 -b -b 5 -c 6
11 3
b 4
b 5
5
getopts .sh
9 -c 6

起初我看到以上的輸出結果百思不得其解,后面多試幾次選項及參數后,大概猜了一下。

第一行輸出echo $*

第二行,optind初值為1,下一個要處理的選項-b位置為3,所以輸出11 3;

第三行,下一個要處理的選項-b位置為4,所以輸出b 4;

第四行,下一個要處理的選項-b位置為5,所以輸出b 5;

程序現在遇到9,不屬於getopts,所以停止循環while,下面幾行就不解釋了。

getopt 與 getopts 都是 Bash 中用來獲取與分析命令行參數的工具,常用在 Shell 腳本中被用來分析腳本參數。

兩者的比較

(1)getopts 是 Shell 內建命令,getopt 是一個獨立外部工具

(2)getopts 使用語法簡單,getopt 使用語法較復雜

(3)getopts 不支持長參數(如:--option ),getopt 支持

(4)getopts 不會重排所有參數的順序,getopt 會重排參數順序(這里的區別下面會說明)

(5)getopts 出現的目的是為了代替 getopt 較快捷的執行參數分析工作

 

1 getopts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
while  getopts  'd:Dm:f:t:'  OPT;  do
     case  $OPT  in
         d)
             DEL_DAYS= "$OPTARG" ;;
         D)
             DEL_ORIGINAL= 'yes' ;;
         f)
             DIR_FROM= "$OPTARG" ;;
         m)
             MAILDIR_NAME= "$OPTARG" ;;
         t)
             DIR_TO= "$OPTARG" ;;
         ?)
             echo  "Usage: `basename $0` [options] filename"
     esac
done
  
shift  $(($OPTIND - 1))

  

getopts后面的字符串就是可以使用的選項列表,每個字母代表一個選項,后面帶:的意味着選項除了定義本身之外,還會帶上一個參數作為選項的值,比如d:在實際的使用中就會對應-d 30,選項的值就是30;getopts字符串中沒有跟隨:的是開關型選項,不需要再指定值,相當於true/false,只要帶了這個參數就是true。如果命令行中包含了沒有在getopts列表中的選項,會有警告信息,如果在整個getopts字符串前面也加上個:,就能消除警告信息了。

使用getopts識別出各個選項之后,就可以配合case來進行相應的操作了。操作中有兩個相對固定的“常量”,一個是OPTARG,用來取當前選項的值,另外一個是OPTIND,代表當前選項在參數列表中的位移。注意case中的最后一個選擇──?,代表這如果出現了不認識的選項,所進行的操作。 

選項參數識別完成之后,如果要取剩余的其它命令行參數,可以使用shift把選項參數抹去,就像例子里面的那樣,對整個參數列表進行左移操作,最左邊的參數就丟失了(已經用case判斷並進行了處理,不再需要了),位移的長度正好是剛才case循環完畢之后的OPTIND - 1,因為參數從1開始編號,選項處理完畢之后,正好指向剩余其它參數的第一個。在這里還要知道,getopts在處理參數的時候,處理一個開關型選項,OPTIND加1,處理一個帶值的選項參數,OPTIND則會加2。 

最后,真正需要處理的參數就是1 1 #了,可以用for循環依次處理。

使用getopts處理參數雖然是方便,但仍然有兩個小小的局限:

1.選項參數的格式必須是-d val,而不能是中間沒有空格的-dval。
2.所有選項參數必須寫在其它參數的前面,因為getopts是從命令行前面開始處理,遇到非-開頭的參數,或者選項參數結束標記--就中止了,如果中間遇到非選項的命令行參數,后面的選項參數就都取不到了。
3.不支持長選項, 也就是--debug之類的選項

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
echo  初始 OPTIND: $OPTIND
  
while  getopts  "a:b:c"  arg  #選項后面的冒號表示該選項需要參數
do
     case  $arg  in
         a)
             echo  "a's arg:$OPTARG"  #參數存在$OPTARG中
             ;;
         b)
             echo  "b's arg:$OPTARG"
             ;;
         c)
             echo  "c's arg:$OPTARG"
             ;;
         ?)   #當有不認識的選項的時候arg為?
             echo  "unkonw argument"
             exit  1
         ;;
     esac
done
  
echo  處理完參數后的 OPTIND:$OPTIND
echo  移除已處理參數個數:$((OPTIND-1))
shift  $((OPTIND-1))
echo  參數索引位置:$OPTIND
echo  准備處理余下的參數:
echo  "Other Params: $@"

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
june@Win7 192.168.1.111 02:32:45 ~ >
bash  b.sh -a 1 -b 2 -c 3   test  -oo xx - test
初始 OPTIND: 1
a's arg:1
b's arg:2
c's arg:
處理完參數后的 OPTIND:6
移除已處理參數個數:5
參數索引位置:6
准備處理余下的參數:
Other Params: 3  test  -oo xx - test
june@Win7 192.168.1.111 02:32:49 ~ >
bash  b.sh -a 1 -c 3 -b 2  test  -oo xx - test    # 非參數選項注意順序與值,不要多傳
初始 OPTIND: 1
a's arg:1
c's arg:
處理完參數后的 OPTIND:4
移除已處理參數個數:3
參數索引位置:4
准備處理余下的參數:
Other Params: 3 -b 2  test  -oo xx - test
june@Win7 192.168.1.111 02:33:14 ~ >
bash  b.sh -a 1 -c -b 2  test  -oo xx - test
初始 OPTIND: 1
a's arg:1
c's arg:
b's arg:2
處理完參數后的 OPTIND:6
移除已處理參數個數:5
參數索引位置:6
准備處理余下的參數:
Other Params:  test  -oo xx - test
june@Win7 192.168.1.111 02:33:22 ~ >

 

2 getopt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Code highlighting produced by Actipro CodeHighlighter (freeware)http: //www .CodeHighlighter.com /-- >
#!/bin/bash
 
# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh
 
# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'
 
# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
 
#-o表示短選項,兩個冒號表示該選項有一個可選參數,可選參數必須緊貼選項
#如-carg 而不能是-c arg
#--long表示長選項
#"$@"在上面解釋過
# -n:出錯時的信息
# -- :舉一個例子比較好理解:
#我們要創建一個名字為 "-f"的目錄你會怎么辦?
# mkdir -f #不成功,因為-f會被mkdir當作選項來解析,這時就可以使用
# mkdir -- -f 這樣-f就不會被作為選項。
 
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
      -n  'example.bash'  --  "$@" `
 
if  [ $? != 0 ] ;  then  echo  "Terminating..."  >&2 ;  exit  1 ;  fi
 
# Note the quotes around `$TEMP': they are essential!
#set 會重新排列參數的順序,也就是改變$1,$2...$n的值,這些值在getopt中重新排列過了
eval  set  --  "$TEMP"
 
#經過getopt的處理,下面處理具體選項。
 
while  true  do
         case  "$1"  in
                 -a|--a-long)  echo  "Option a"  shift  ;;
                 -b|--b-long)  echo  "Option b, argument \`$2'"  shift  2 ;;
                 -c|--c-long)
                         # c has an optional argument. As we are in quoted mode,
                         # an empty parameter will be generated if its optional
                         # argument is not found.
                         case  "$2"  in
                                 "" echo  "Option c, no argument" shift  2 ;;
                                 *)   echo  "Option c, argument \`$2'"  shift  2 ;;
                         esac  ;;
                 --)  shift  break  ;;
                 *)  echo  "Internal error!"  exit  1 ;;
         esac
done
echo  "Remaining arguments:"
for  arg  do
    echo  '--> ' "\`$arg'"  ;
done

 一個例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
 
ARGS=`getopt -o  "ao:"  -l  "arg,option:"  -n  "getopt.sh"  --  "$@" `
 
eval  set  --  "${ARGS}"
 
while  true do
     case  "${1}"  in
         -a|--arg)
         shift ;
         echo  -e  "arg: specified"
         ;;
         -o|--option)
         shift ;
         if  [[ -n  "${1}"  ]];  then
             echo  -e  "option: specified, value is ${1}"
             shift ;
         fi
         ;;
         --)
         shift ;
         break ;
         ;;
     esac
done

  

1
2
3
4
5
6
7
8
# ./getopt.sh -a
arg: specified
# ./getopt.sh -a -o Apple
arg: specified
option: specified, value is Apple
# ./getopt.sh --arg --option Apple
arg: specified
option: specified, value is Apple


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM