1. 程式人生 > >shell指令碼選項設定及解析

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一覽
&quot;* 所有引數列表。如&quot;*“用「”」括起來的情況、以"$1 $2 … $n"的形式輸出所有引數。
@&quot;@ 所有引數列表。如&quot;@“用「”」括起來的情況、以"$1" “2&quot;&quot;2&quot; … &quot;n” 的形式輸出所有引數。
$#
新增到Shell的引數個數
$0
Shell本身的檔名
11~n
新增到Shell的各引數值。$1是第1引數、$2是第2引數…。

延伸閱讀: