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
|