shell指令碼選項設定及解析
shell指令碼的選項
比較複雜的shell指令碼通常都會支援多個選項及其輸入. 通常形式為-[a-z,A-Z] [filename/settings]
. 在控制檯輸入指令碼名稱時,還會顯示出幫助資訊.
顯示幫助
可以定義一個Usage() {}函式作為指令碼的幫助函式, 當幫助資訊比較簡單的時候,可以echo命令實現, 當引數比較多的時候,可以用cat工具配合EOF符號來定義大段的說明文字. 例如:
Usage() { cat <<EOF bet <input> <output> [options] -d debug (do not delete temporary intermediate images) EOF exit 1 } # 顯示幫助 [ "$1" = "" ] && Usage
這裡bet命令的呼叫格式定義為:bet <input> <output> [options]
,這也是一種常見的shell指令碼引數格式. 當options比較多的時候,shell指令碼沒有python裡面argpase這樣的工具包, 應該如何解析這些引數設定呢? 這時候還是要具體問題具體分析. 實際上,shell指令碼對引數的讀取和解析也是非常靈活的.
簡單的選項引數
如果引數只是類似於-a, -N這種簡單的識別符號. 可以用簡單的if …then … fi 語句解析:
if [ $1 = -a ] ; then REG="-a" HOWLONG=5 fi
複雜的選項引數
如果引數後面還有具體的配置檔名稱或者選項,也就是說 -a, -N這類字首後續還有具體的設定字串, 例如引數說明如下:
-T <minutes> Estimated job length in minutes, used to auto-set queue name -q <queuename> Possible values for <queuename> are "verylong.q", "long.q" and "short.q". See below for details Default is "long.q". -a <arch-name> Architecture [e.g., darwin or lx24-amd64] -p <job-priority> Lower priority [0:-1024] default = 0 -M <email-address> Who to email, default = `whoami`@fmrib.ox.ac.uk -j <jid> Place a hold on this task until job jid has completed -t <filename> Specify a task file of commands to execute in parallel -N <jobname> Specify jobname as it will appear on queue -R <RAM> Max total RAM to use for job (integer in MB) -l <logdirname> Where to output logfiles -m <mailoptions> Change the SGE mail options, see qsub for details -z <output> If <output> image or file already exists, do nothing and exit -F Use flags embedded in scripts to set SGE queuing options -s <pename>,<threads> Submit a multi-threaded task - requires a PE (<pename>) to be configured for the requested queues. <threads> specifies the number of threads to run -v Verbose mode.
那麼可以採用這樣的方式:
nargs=$#
if [ $nargs -eq 0 ] ; then
usage
fi
set -- `getopt T:q:a:p:M:j:t:z:N:R:Fvm:l:s: $*`
result=$?
if [ $result != 0 ] ; then
echo "What? Your arguments make no sense!"
fi
if [ $nargs -eq 0 ] || [ $result != 0 ] ;
then usage
fi
上面指令碼片段中, 最重要的是如下一段:
set -- `getopt T:q:a:p:M:j:t:z:N:R:Fvm:l:s: $*`
這一句很關鍵. 其中用到了兩個命令列工具: getopt和set. getopt的呼叫方法是這樣的:
getopt options optstring parameters
這裡的optstring是T:q:a:p:M:j:t:z:N:R:Fvm:l:s:
帶值選項要在字母后加冒號(:),可以將類似功能的字首符號放在一起, 就像這句裡的"Fvm" .如果引數中包含無效引數,那麼會給出錯誤資訊.
當getopt將引數格式化好了之後,由set替換掉命令列原始引數。例如:
#!/bin/bash
set -- `getopt a:b:c "[email protected]"`
echo "param = [email protected]"
while [ -n "$1" ]
do
case "$1" in
-a) echo "found option a and param = $2"
shift ;;
-b) echo "found option b and param = $2"
shift ;;
-c) echo "found option c, no param." ;;
--) ;;
*) echo "what's this?"
break ;;
esac
shift
done
儲存檔名稱為getopt_test. 得到的輸出如下:
$ getopt_test -a test -b test -e
getopt: invalid option -- 'e'
param = -a test -b test --
found option a and param = test
found option b and param = test
最後, 附上shell指令碼中特殊符號的含義
Shell指令碼中$0、$?、$!、$$、$*、$#、[email protected]
等的意義
$$
Shell本身的PID(ProcessID)
$!
Shell最後執行的後臺Process的PID
$?
最後執行的命令的結束程式碼(返回值)
$-
使用Set命令設定的Flag一覽
*“用「”」括起來的情況、以"$1 $2 … $n"的形式輸出所有引數。
@“用「”」括起來的情況、以"$1" “n” 的形式輸出所有引數。
$#
新增到Shell的引數個數
$0
Shell本身的檔名
n
新增到Shell的各引數值。$1是第1引數、$2是第2引數…。