講解一:
shell
getopts能夠編寫腳本,使控制多個命令行參數更加容易。getopts用於造成命令行處理標
準形式。原則上講,腳本應具備確認帶有多個選項的命令文件標準格式的能力。編程
2.1 getopts腳本實例
經過例子能夠更好地理解getopts。如下getopts腳本接受下列選項或參數。
a 設置變量ALL爲true
h 設置變量HELP爲truebash
f 設置變量FILE爲true
v 設置變量VERBOSE爲true框架
對於全部變量設置,通常總假定其初始狀態爲false:ide
[sam@chenwy sam]$ ./getopt1 -a -h
ALL is true
HELP is true
[sam@chenwy sam]$ cat getopt1
#!/bin/sh
ALL=false
HELP=false
FILE=false
VERBOSE=falseui
while getopts ahfgv OPTION
do
case $OPTION in
a)ALL=true
echo "ALL is $ALL"
;;
h)HELP=true
echo "HELP is $HELP"
;;
f)FILE=true
echo "FILE is $FILE"
;;
v)VERBOSE=true
echo "VERBOSE is $VERBOSE"
;;
esac
donespa
getopts通常格式爲:
getopts option_string variable
在上述例子中使用腳本:
while getopts ahfgv OPTION
能夠看出while循環用於讀取命令行,options_string爲指定的5個選項(-a,-h,-f,-g,-v),腳本中varible爲OPTION。注意這裏並無用連字符指定每一單個選項。
運行上述腳本,給出幾個有效和無效的選項,結果爲:命令行
[sam@chenwy sam]$ ./getopt1 -a -h
ALL is true
HELP is true
[sam@chenwy sam]$ ./getopt1 -a -h -p
ALL is true
HELP is true
./getopt1: illegal option -- p
[sam@chenwy sam]$ ./getopt1 -p
./getopt1: illegal option -- p調試
能夠看出不一樣選項的結合方式。xml
2.2 getopts使用方式
getopts讀取option_string,獲知腳本中使用了有效選項。
getopts查看全部以連字符開頭的參數,將其視爲選項,若是輸入選項,將把這與option_string對比,若是匹配發現,變量設置爲OPTION,若是未發現匹配字符,變量可以設置爲?。重複此處理過程直到選項輸入完畢。
getopts接收完全部參數後,返回非零狀態,意即參數傳遞成功,變量OPTION保存最後處理參數,一下子就能夠看出處理過程當中這樣作的好處。
2.3 使用getopts指定變量取值
有時有必要在腳本中指定命令行選項取值。getopts爲此提供了一種方式,即在option_string中將一個冒號放在選項後。例如:
getopts ahfvc: OPTION
上面一行腳本指出,選項a、h、f、v能夠不加實際值進行傳遞,而選項c必須取值。使用選項取值時,必須使用變量OPTARG保存該值。若是試圖不取值傳遞此選項,會返回一個錯誤信息。錯誤信息提示並不明確,所以能夠用本身的反饋信息屏蔽它,方法以下:
將冒號放在option_string開始部分。
while getopts :ahfgvc: OPTION
在case語句裏使用?建立一可用語句捕獲錯誤。
[sam@chenwy sam]$ cat getopt1
#!/bin/sh
ALL=false
HELP=false
FILE=false
VERBOSE=false
COPIES=0
while getopts :ahfgvc: OPTION
do
case $OPTION in
a)ALL=true
echo "ALL is $ALL"
;;
h)HELP=true
echo "HELP is $HELP"
;;
f)FILE=true
echo "FILE is $FILE"
;;
v)VERBOSE=true
echo "VERBOSE is $VERBOSE"
;;
c)COPIES=$OPTARG
echo "COPIES is $COPIES"
;;
?)
echo "`basename ` -[a h f v] -[c value] file"
;;
esac
done
輸入全部合法選項:
[sam@chenwy sam]$ ./getopt1 -ah -c 3
ALL is true
HELP is true
COPIES is 3
選項- c不賦值,將返回錯誤,但顯示的是腳本語句中的反饋信息
[sam@chenwy sam]$ ./getopt1 -ah -c
ALL is true
HELP is true
getopt1 -[a h f v] -[c value] file
去掉前面的冒號,提到系統的提示消息
:[sam@chenwy sam]$ ./getopt1 -ah -c
ALL is true
HELP is true
./getopt1: option requires an argument -- c
2.4 訪問取值方式
getopts的一種功能是運行後臺腳本。這樣可使用戶加入選項,指定不一樣的磁帶設備以備份數據。使用getopts實現此任務的基本框架以下:
[sam@chenwy sam]$ cat backups
#!/bin/sh
OUITE=n
DEVICE=awa
LOGFILE=/tmp/logbackup
usage()
{
echo "Usage: `basename ` -d [device] -l [logfile] -q"
exit 1
}
if [ $# = 0 ]
then
usage
fi
while getopts :qd:l: OPTION
do
case $OPTION in
q) QUIET=y
LOGFILE="/tmp/backup.log"
;;
d)DEVICE=$OPTION
;;
l)LOGFILE=$OPTARG
;;
?)usage
;;
esac
done
echo "you chlose the ..."
echo "Quite=$QUIET $DEVICE $LOGFILE"
上述腳本中若是指定選項d,則需爲其賦值。該值爲磁帶設備路徑。用戶也能夠指定是否備份輸出到登陸文件中的內容。運行上述腳本,指定下列輸入:
[sam@chenwy sam]$ ./backups -d /dev/rmt0 -q
you chlose the ...
Quite=y d /tmp/backup.log
getopts檢查完以後,變量OPTARG取值可用來進行任何正常的處理過程。固然,若是輸入選項,怎樣進行進一步處理及使該選項有有效值,徹底取決於用戶。
以上是使用getopts對命令行參數處理的基本框架。
實際處理文件時,使用for循環,就像在tr-case腳本中使用shift命令過濾全部選項同樣。
使用getopts與使用shift方法比較起來,會減小大量的編程工做。
2.5 使用getopts處理文件轉換
如今用所學知識將tr-case腳本轉換爲getopts版本。命令行選項getopts方法與shift方法的惟一區別是一個VERBOSE選項。
變量VERBOSE缺省取值爲no,但選擇了命令行選項後,case語句將捕獲它,並將其設爲yes,反饋的命令是一個簡單的if語句。
if [ "VERBOSE" = "on" ];
thenecho "doing upp on $LOOP ..newfile called $LOOP$EXT"
fi
若是正在使用其餘系統命令包,它老是反饋用戶動做,只需簡單地將包含錯誤的輸出重定向到/dev/null中便可。如:
命令>/dev/null 2 >&1
缺省時VERBOSE關閉(即不顯示),使用- v選項可將其打開。例如要用VERBOSE將myfile文件系列轉換爲小寫,方法以下:
tr-case -l -v myfile1 myfile2 ...
或者
tr-case -v -l myfile1 myfile2 ...
可能首先注意的是使用g e t o p t s後腳本的縮減效果。這裏用於文件處理的腳本與s h i f t版本相同。
腳本以下:
[sam@chenwy sam]$ cat tr_case1
#!/bin/sh
FILES=""
TRCASE=""
EXT=""
OPT=no
VERBOSE="off"
while getopts :luv OPTION
do
case $OPTION in
l)TRCASE="lower"
EXT=".LC"
OPT=yes
;;
u)TRCASE="upper"
EXT=".UC"
OPT=yes
;;
v)VERBOSE=on
;;
?)echo "usage: `basename `: -[l|u] -v file[s]"
exit 1
;;
esac
done
shift `expr $OPTIND - 1`
if [ "$#" = "0" ] || [ "$OPT" = "no" ]
then
echo "usage: `basename `: -[l|u] -v file[s]"
exit 1
fi
for LOOP in "$@"
do
if [ ! -f $LOOP ]
then
echo "`basename ` :error cannot find file $LOOP"
exit 1
fi
echo $TRCASE $LOOP
case $TRCASE in
lower) if [ "VERBOSE" = "on" ];then
echo "doing...lower on $LOOP..newfile"
fi
cat $LOOP|tr "[a-z]" "[A-Z]" > $LOOP$EXT
;;
upper) if [ "VERBOSE" = "on" ];then
echo "doing upper on $LOOP..newfile"
fi
cat $LOOP|tr "[A-Z]" "[a-z]" >$LOOP$EXT
;;
esac
done
在腳本中指定命令行選項時,最好使其命名規則與U N I X或L I N U X一致。下面是一些選項及其含義的列表。
選項含義
- a 擴展
- c 計數、拷貝
- d 目錄、設備
- e 執行
- f 文件名、強制
- h 幫助
- i 忽略狀態
- l 註冊文件
- o 完整輸出
- q 退出
- p 路徑
- v 顯示方式或版本
3 小結
正確控制命令行選項會使腳本更加專業化,對於用戶來講會使之看起來像一個系統命令。
本章講到了控制命令行選項的兩種方法,shift和getopts。使用getopts檢測腳本的數量遠遠小於使用s h i f t方法檢測腳本的數量。
shift也克服了腳本參數$ 1 . . $ 9的限制。使用shift命令,腳本能夠很容易偏移至全部調用參數,所以腳本能夠作進一步處理。
講解二:
處理命令行參數,並校驗有效選項。
getopts 命令是 Korn/POSIX shell 的內置命令,用來從參數列表檢索選項以及選項參數。選項由一個+(加號)或者是由一個-(減號)後跟一個字符開始。一個既不是以+,也不是以-開始的選項結束選項字符串。每次調用 getopts 命令時,它將下一個選項的值放置在名稱內,並將下一個要處理的參數的索引置於 shell 變量 OPTIND 中。一旦調用了shell , OPTIND 將初始化爲1。當選項以 +開頭,則+ 將預先設爲名稱中的值。
若是選項字符串中的字符後面帶有「:」(冒號),則預期此選項將帶有參數。當選項須要選項參數時,getopts 命令就將其置於變量 OPTARG 中。
當查找到選項字符串所不包含的選項字符,或者查找到的選項沒有所需的選項參數時:
若是選項字符串不以:(冒號)開頭,名稱 將會被設置爲 ?(問號)字符,OPTARG. 將被取消設置,而且診斷消息將被寫入到標準錯誤中。
這種狀況被認爲是在將參數傳遞給所調用的應用程序的過程當中所檢測到的錯誤,而不是在處理 getopts 命令的過程當中所發生的錯誤;如上所述,寫入診斷消息,但退出狀態將變爲零。
若是選項字符串以 :(冒號)開頭,名稱 將被設爲 ? (問號)字符,這是對未知的選項來講的,或者爲缺乏的所需選項設爲:(冒號)字符,OPTARG 將被設置爲已查找到的選項字符,而且 標準錯誤中將不寫入任何輸出。
如下任何字符均可以識別選項結尾:特殊選項- -,查找到不以-,或者+爲開頭的參數,或者遇到錯誤。
當遇到選項結尾時:
getopts 命令將退出運行,而且返回值大於零,OPTARG 將被設置爲第一個非選項參數索引,在這種狀況下,若是第一個 - - 參數以前未出現其它非選項參數,將認爲它是選項參數,或者若是沒有非選項參數,設置爲值 $#+1,名稱將被設置爲? (問號)字符,
選項字符串
包含 getopts 命令識別的選項字符串。若是字符後帶有冒號,則預期選項將帶有參數,應該以單獨參數的形式提供此參數。能夠用空格將選項與參數分隔開。若是選項字符是未知的或者選項參數丟失,則選項字符串中的第一個字符將決定 getopts 命令的行爲。
注意:應用程序不該該將問號和冒號字符做爲選項字符。使用其它非字母數字的字符會產生不明的結果。
名稱
由 getopts 命令對查找到的選項字符設置。
參數 ...
一個或多個被空格分隔的字符串,由 getopts 命令校驗是不是合法選項。若是省略參數 ,就使用位置參數。有關位置參數的更多信息,請參見 Korn Shell 中的 參數替換。
注意: 通常來講,沒必要將參數指定爲 getopts 命令的一部分,但在進行腳本調試時可能會有所幫助。
此命令返回下列出口值:
0
查找到由選項字符串指定的或未指定的選項。
<0
遇到選項結束或發生錯誤。
下列 getopts 命令規定 a、b 和 c 爲有效選項,而且選項 a 和 c 帶有參數:
getopts a:bc: OPT
下列 getopts 命令指定 a、b 以及 c 爲有效選項, 而且選項 a 和 b 帶有參數,並且 getopts 在命令行遇到爲定義的選項時,它將 OPT 的值設置爲 ?:
getopts :a:b:c OPT
下列腳本分析和顯示其參數:
aflag= bflag= while getopts ab: name do case $name in a) aflag=1;; b) bflag=1 bval="$OPTARG";; ?) printf"Usage: %s: [-a] [-b value] args\n" $0 exit 2;; esac done if [ ! -z "$aflag" ]; then printf "Option -a specified\ n" fi if [ ! -z "$bflag" ]; then printf'Option -b "%s" specified\ n' "$bval" fi shift $(($OPTIND -1)) printf "Remaining arguments are: %s\n" "$*"
在Bash裏有如下用途:
optstring option 字符串,會逐個匹配
varname 每次匹配成功的選項
arg 參數列表,沒寫時它會取命令行參數列表
$OPTIND 特殊變量,option index,會逐個遞增
$OPTARG 特殊變量,option argument,不一樣狀況下有不一樣的值
細則1:當optstring以」:「開頭時,getopts會區分invalid option錯誤和miss option argument錯誤。
invalid option時,varname會被設成?,$OPTARG是出問題的option;
miss option argument時,varname會被設成:,$OPTARG是出問題的option。
若是optstring不以」:「開頭,invalid option錯誤和miss option argument錯誤都會使
varname被設成?,$OPTARG是出問題的option。
細則2:當optstring中的字母跟」:「時,代表該option可接參數,參數(argument)放在$OPTARG中;
若是缺參數,且optstring是以」:「開頭,則varname的值會是:,$OPTARG是該option,
不然varname的值是?,$OPTARG是該option。(參照細則1)
例子:gg.sh
[root@localhost shel]# cat gg.sh
#gg.sh
#!/bin/bash
while getopts "abc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG # 這裏$OPTIND 是一個索引序列號,$OPTARG 是選項裏所記錄的值,無值是爲空,默認狀況下選項是以空格分隔
done
echo "Resetting"
OPTIND=1 while getopts "abc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG
done
[root@localhost shel]# ./gg.sh -ab -c foo -f "foo bar" -h -gde
a 1
b 2
c 4 foo
f 6 foo bar
h 7
g 7
d 7
e 8
Resetting
a 1
b 2
c 4 foo
f 6 foo bar
h 7
g 7
d 7
e 8
上面是顯示結果。
若是調整一下所給參數的位置:
[root@localhost shel]# ./gg.sh -abc foo -f "foo bar" -h –gde a 1b 1c 3 foof 5 foo barh 6g 6d 6e 7Resettinga 1b 1c 3 foof 5 foo barh 6g 6d 6e 7