天天看點

使用 getopt 處理指令行長參數(長選項)

getopt指令并不是bash的内建指令,它是由util-linux包提供的外部指令。

getopt 與 getopts 的差別

  • getopts 是 shell 内建指令, getopt 是一個獨立外部工具
  • getopts 使用文法簡單,getopt 使用文法複雜
  • getopts 不支援長參數(長選項,如 --option), getopt 支援
  • getopts 不會重排所有參數的順序,getopt會重排參數順序 (getopts 的 shell 内置 OPTARG 這個變量,getopts 通過修改這個變量依次擷取參數,而 getopt 必須使用 set 來重新設定位置參數,然後在 getopt 中使用 shift 來依次擷取參數)
  • 如果某個參數中含有空格,那麼這個參數就變成了多個參數。是以,基本上,如果參數中可能含有空格,那麼必須用getopts(新版本的 getopt 也可以使用空格的參數,隻是傳參時,需要用 雙引号 包起來)。

getopt 指令選項說明:

getopt 指令的選項說明:
-a 使getopt長選項支援"-"符号打頭,必須與-l同時使用
-l 後面接getopt支援長選項清單
-n program如果getopt處理參數傳回錯誤,會指出是誰處理的這個錯誤,這個在調用多個腳本時,很有用
-o 後面接短參數選項,這種用法與getopts類似,
-u 不給參數清單加引号,預設是加引号的(不使用-u選項),例如在加不引号的時候 --longopt "select * from db1.table1" $2隻會取到select ,而不是完整的SQL語句。

選項的使用定義規則類似 getopts :
例如
ab:c::

意思是:
a 後沒有冒号,表示沒有可以參數
b 後跟一個冒号,表示有一個必要的參數
c 後跟兩個冒号,表示有一個可選的參數(參數必須緊挨着選項)
長選項的定義相同,但用逗号分割。
           

示例:

#!/bin/bash

#定義選項, -o 表示短選項 -a 表示支援長選項的簡單模式(以 - 開頭) -l 表示長選項 
# a 後沒有冒号,表示沒有參數
# b 後跟一個冒号,表示有一個必要參數
# c 後跟兩個冒号,表示有一個可選參數(可選參數必須緊貼選項)
# -n 出錯時的資訊
# -- 也是一個選項,比如 要建立一個名字為 -f 的目錄,會使用 mkdir -- -f ,
#    在這裡用做表示最後一個選項(用以判定 while 的結束)
# [email protected] 從指令行取出參數清單(不能用用 $* 代替,因為 $* 将所有的參數解釋成一個字元串
#                         而 [email protected] 是一個參數數組)
    
TEMP=`getopt -o ab:c:: -a -l apple,banana:,cherry:: -n "test.sh" -- "[email protected]"`

# 判定 getopt 的執行時候有錯,錯誤資訊輸出到 STDERR
if [ $? != 0 ]
then
	echo "Terminating....." >&2
	exit 1
fi

# 重新排列參數的順序
# 使用eval 的目的是為了防止參數中有shell指令,被錯誤的擴充。
eval set -- "$TEMP"

# 處理具體的選項
while true
do
	case "$1" in
		-a | --apple | -apple)
			echo "option a"
			shift
			;;
		-b | --banana | -banana)
			echo "option b, argument $2"
			shift 2
			;;
		-c | --cherry | -cherry)
			case "$2" in
				"") # 選項 c 帶一個可選參數,如果沒有指定就為空
					echo "option c, no argument"
					shift 2
					;;
				*)
					echo "option c, argument $2"
					shift 2
			esac
			;;
		--)
			shift
			break
			;;
		*) 
			echo "Internal error!"
			exit 1
			;;
		esac

done

#顯示除選項外的參數(不包含選項的參數都會排到最後)
# arg 是 getopt 内置的變量 , 裡面的值,就是處理過之後的 [email protected](指令行傳入的參數)
for arg do
   echo '--> '"$arg" ;
done
           

繼續閱讀