以前我總想知道如何為我的bash腳本建立指令行參數。經過搜尋,我發現了2個函數可以處理這個問題,getopt 函數和 getopts 函數。我無意争論哪一個函數更好的。getopts 是一個shell内建指令,而且似乎比 getopt 更容易實作這個功能,是以在這篇文章裡我準備講講getopts。

<a target="_blank"></a>
開始的時候,我隻試着處理傳遞給腳本的指令行參數。最後,我添加了另外一些有用的功能函數,使得這個腳本可以成為其他任何互動式腳本處理指令行的開始模闆。我還添加了一個純文字格式的幫助函數,讓腳本更加容易閱讀。
與其來一長段文字解釋 getopts 在bash中是如何工作的,我認為不如直接來一個能工作的腳本更讓人覺得輕松一些。
#!/bin/bash
######################################################################
#this is an example of using getopts in bash. it also contains some
#other bits of code i find useful.
#author: linerd
#website: http://tuxtweaks.com/
#copyright 2014
#license: creative commons attribution-sharealike 4.0
#http://creativecommons.org/licenses/by-sa/4.0/legalcode
#set script name variable
script=`basename ${bash_source[0]}`
#initialize variables to default values.
opt_a=a
opt_b=b
opt_c=c
opt_d=d
#set fonts for help.[譯注: 這裡tput用來更改終端文本屬性,比如加粗,高亮等]
norm=`tput sgr0`
bold=`tput bold`
rev=`tput smso`
#help function
function help {
echo -e \\n"help documentation for ${bold}${script}.${norm}"\\n
echo -e "${rev}basic usage:${norm} ${bold}$script file.ext${norm}"\\n
echo "command line switches are optional. the following switches are recognized."
echo "${rev}-a${norm} --sets the value for option ${bold}a${norm}. default is ${bold}a${norm}."
echo "${rev}-b${norm} --sets the value for option ${bold}b${norm}. default is ${bold}b${norm}."
echo "${rev}-c${norm} --sets the value for option ${bold}c${norm}. default is ${bold}c${norm}."
echo "${rev}-d${norm} --sets the value for option ${bold}d${norm}. default is ${bold}d${norm}."
echo -e "${rev}-h${norm} --displays this help message. no further functions are performed."\\n
echo -e "example: ${bold}$script -a foo -b man -c chu -d bar file.ext${norm}"\\n
exit 1
}
#check the number of arguments. if none are passed, print help and exit.
numargs=$#
echo -e \\n"number of arguments: $numargs"
if [ $numargs -eq 0 ]; then
help
fi
### start getopts code ###
#parse command line flags
#如果選項需要後跟參數,在選項後面加":"
#注意"-h"選項後面沒有":",因為他不需要參數。選項字元串最開始的":"是用來去掉來自getopts本身的報錯的,同時擷取不能識别的選項。(譯注:如果選項字元串不以":"開頭,發生錯誤(非法的選項或者缺少參數)時,getopts會向錯誤輸出列印錯誤資訊;如果以":"開頭,則不會列印[在man中叫slient error reporting],同時将出錯的選項賦給optarg變量)
while getopts :a:b:c:d:h flag; do
case $flag in
a) #set option "a"
opt_a=$optarg
echo "-a used: $optarg"
echo "opt_a = $opt_a"
;;
b) #set option "b"
opt_b=$optarg
echo "-b used: $optarg"
echo "opt_b = $opt_b"
c) #set option "c"
opt_c=$optarg
echo "-c used: $optarg"
echo "opt_c = $opt_c"
d) #set option "d"
opt_d=$optarg
echo "-d used: $optarg"
echo "opt_d = $opt_d"
h) #show help
\?) #unrecognized option - show help
echo -e \\n"option -${bold}$optarg${norm} not allowed."
#在這裡如果你不想列印完整的幫助資訊,隻想顯示簡單的錯誤資訊,去掉上面的兩行,同時使用下面的兩行。
#echo -e "use ${bold}$script -h${norm} to see the help documentation."\\n
#exit 2
esac
done
shift $((optind-1)) #this tells getopts to move on to the next argument.
### end getopts code ###
### main loop to process files ###
#這裡你可以用你的腳本處理邏輯來替代。這個例子隻是在終端中列印檔案的檔案名和字尾名。你可以把任意其他的檔案處理任務放到這個while-do循環中。
while [ $# -ne 0 ]; do
file=$1
tempfile=`basename $file`
#tempfile="${file##*/}" #另外一種擷取不帶字尾的檔案名的方法。
file_base=`echo "${tempfile%.*}"` #file without extension
file_ext="${tempfile##*.}" #file extension
echo -e \\n"input file is: $file"
echo "file withouth extension is: $file_base"
echo -e "file extension is: $file_ext"\\n
shift #move on to next input file.
### end main loop ###
exit 0
将上面的代碼複制到你的文本編輯器裡,然後儲存到你的可執行路徑下。我将這個腳本命名為 options 并儲存到 /home/linerd/bin 路徑下。儲存之後記得給你的腳本添加可執行權限。
chmod +x ~/bin/options
現在腳本已經可以運作了。試試用 -h 參數來列印幫助資訊吧。
options -h
遇到不支援的選項,腳本同樣可以給出提示,并列印幫助資訊。
options -z
最後,getopts可以以任意的順序處理你給的指令行參數。唯一的限制是你要處理的檔案必須放在所有參數的最後。
options -d bar -c chu -b man -a foo example1.txt example2.txt
你會用getops來幹什麼呢?在評論裡告訴我吧。
原文釋出時間:2014-06-16
本文來自雲栖合作夥伴“linux中國”