getopts簡易教程(Small getopts tutorial)譯文

getopts簡易教程

當你想用一種專業的方式解析命令行參數時,getopts就是要選擇的工具。和它的舊版本兄弟命令getopt不一樣(注意沒有s!),getopts是shell內置命令。高級地方表如今html

  • 你不須要經過一個外部命令傳遞參數
  • getopts能夠很容易的設置一些你能用於解析參數的變量(對於一個外部程序來講這是不可能的!)
  • 你沒必要再處理過去一些使用getopt時的一些bug實現(空格, …)
  • getopts已經在POSIX®定義

一些解析位置參數的其餘方法(不用getopt(s))在這裏介紹了: 如何處理位置參數.算法

注意getopts不能解析GNU風格的長選項(--myoption)或XF86風格的長選項(-myoption)!shell

介紹

術語

須要先了解一下咱們這裏探討的事情,因此讓咱們來看一個範例… 來看一下下面這行命令:數組

mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt

全部這些都叫位置參數,可是你能夠把他們分紅一些邏輯組:bash

  • -x是一個選項, 一個標識, 一個開關: 一個字符, 有一個前引導短橫槓(-)
  • -f也是一個選項,可是這個選項有一個附加參數(傳遞給-f選項的參數): /etc/mybackup.conf。這個參數一般與它的參數分開(使用一個空格或其餘分隔符), 但這不是必須的, -f/etc/mybackup.conf也是合法的。
  • -r依賴於配置。在這個範例中,-r不須要參數,因此它是獨立的選項,像-x
  • ./foo.txt和./bar.txt是剩餘的參數,不與任何選項關聯。這些一般用做聚合參數(好比你指定給cp(1)的文件名)或者不須要選項的參數,由於這是程序的預約義格式(就像你傳遞給文本編輯器的文件名參數,用於打開和顯示文本 - 爲什麼還須要一個額外的開關呢?). POSIX®調用它們做爲操做對象

讓你體會一下爲何getopts頗有用: 上面的命令能夠像這樣讀取…編輯器

mybackup -xrf /etc/mybackup.conf ./foo.txt ./bar.txt

…使用本身的代碼去解析很困難。而getopts能夠認出全部常見的選項格式。函數

選項標識能夠有大小寫,也能夠是數字。甚至是其餘可識別字符,可是並不推薦這麼作(可用性差並且特殊字符可能會出問題)。工具

原理

通常你須要調用getopts好幾回。每次會使用"下一個"位置參數(和一個可能的附加參數),若是解析成功,會給你返回結果。getopts不會改變位置參數的設定 —— 若是你想要shift掉參數,你必須手工處理:oop

shift $((OPTIND-1))
# now do something with $@

由於getopts在沒有要解析的參數剩餘時會返回退出狀態_FALSE_,因此能夠很容易的在while循環使用:測試

while getopts ...; do
  ...
done

getopts將會解析選項和他們可能的參數。遇到第一個非選項的參數時將會中止解析(一個不以連字符(-)開頭的字符串,這不是前面任何一個選項的參數)。一樣也會在看到--(雙連字符)時中止解析,由於這個含義是選項終止

有用的變量

變量 描述
OPTIND 保存下一個要解析的參數的指針。這就是getopts如何"記住"本身的狀態和回調請求。一樣能夠用於在getopts處理過以後shift掉位置參數。OPTIND初始爲1, 若是你想要再次使用getopts解析任何參數時須要從新設置爲1
OPTARG 這個變量設置爲被getopts發現的選項的參數。一樣包含了未知的選項標記
OPTERR (可選值0或1)代表Bash是否應該顯示getopts內置的錯誤信息。該值在每一個shell啓動的時候會被初始化爲1 - 因此若是你不想看到煩人的信息請務必設置爲0!

getopts一樣使用這些變量用於錯誤報告(they're set to value-combinations which arent possible in normal operation).#括號裏面的不會翻譯,預留

指明你想要作的

getopts的基本語法是:

getopts OPTSTRING VARNAME [ARGS...]

解釋:

選項 說明
OPTSTRING 告訴getopts指望哪一個選項和指望的參數在哪裏(參考下面的)
VARNAME 告訴getopts哪一個shell變量用於選項報告
ARG 告訴getopts將這些解析爲附加單詞而不是位置參數

option-string

option-string告訴getopts指望哪一個選項,而且哪一個選項必須有參數。語法很是簡單 -- 每一個字母就是選項名自己,下面這個範例告訴getopts尋找-f, -A和-x:

getopts fAx VARNAME

當你想讓getopts對某個選項指望一個參數時,只是在這個選項標記後面放置一個:(冒號)。若是你想讓-A指望一個參數(例如變成 -A SOMETHING),只須要:

getopts fA:x VARNAME

若是option-string首個字母是:(冒號),一般是荒謬的,由於沒有任何選項在它以前,這種狀況下,getopts會切換到"靜默錯誤報告"模式。在產品腳本中,這一般就是你想要的結果(自行抓取錯誤信息處理,不要被煩人的信息所幹擾)。

自定義參數解析

getopts工具會默認解析當前shell或函數的位置參數(意味着它解析的是"$@")。

你能夠給出你本身的一組參數解析。當附加參數在VARNAME參數以後給出時,getopts並不試圖解析這些位置參數。

用這種方式,你能夠按照你喜歡的方式解析任何選項,這裏是一個數組的範例:

while getopts :f:h opt "${MY_OWN_SET[@]}"; do
  ...
done

不帶這些附加參數調用getopts的方式等同於顯式的使用"$@"調用:

getopts ... "$@"

錯誤報告

關於錯誤報告,getops能夠在兩種模式下運行:

  • 詳盡模式
  • 安靜模式

對於產品腳本我建議使用靜默模式,由於這樣看起來更專業,你不想看到更多煩人的信息。一樣也更容易處理,失敗的用例都以更簡單的方式顯示。

詳盡模式

選項 說明
invalid option VARNAME is set to ? (quersion-mark) and OPTARG is unset
required argument not found VARNAME is set to ? (quersion-mark), OPTARG is unset and an error message is printed

安靜模式

選項 說明
invalid option VARNAME is set to ? (question-mark) and OPTARG is set to the (invalid) option character
required argument not found VARNAME is set to : (colon) and OPTARG contains the option-character in question

開搞

第一個例子

足夠說明一些問題!

讓咱們先看一個很是簡單的實例: 只有一個指望的選項(-a),沒有任何參數。一樣咱們用帶:(冒號)的option string爲了禁用詳盡錯誤顯示:

#!/bin/bash

while getopts ":a" opt; do
  case $opt in
    a)
      echo "-a was triggered!" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      ;;
  esac
done

我把這些內容放到一個文件go_test.sh,就是你接下來看到的範例中的名字。

來讓咱們作一些測試:

不帶任何參數調用

$ ./go_test.sh
$

什麼都沒發生?對的,getopts沒看到任何合法或非法的選項(前面有短橫線的字母),因此不會觸發。

以非選項的參數調用

$ ./go_test.sh /etc/passwd
$

仍是 — 什麼都沒發生。很是相似的用例: getopts沒看到任何合法或非法的選項(前面有短橫線的字母),因此不會觸發。

傳遞給你的腳本的參數固然能夠用$1 - ${N}獲取。

用選項參數調用

如今讓咱們觸發一下getopts: 提供選項。

首先,來一個非法的:

$ ./go_test.sh -b
Invalid option: -b
$

和預期的同樣,getopts不容許這個選項,像上面說的同樣: It placed ? into $opt and the invalid option character (b) into $OPTARG. 咱們的用例就驗證了這一點。

如今,來一個合法的(-a):

$ ./go_test.sh -a
-a was triggered!
$

你看到了,這個探測結果運行的很完美。在咱們的用例a選項放在了變量$opt中。

固然在調用的時候能夠組合有效和無效的選項:

$ ./go_test.sh -a -x -b -c
-a was triggered!
Invalid option: -x
Invalid option: -b
Invalid option: -c
$

最後,天然也能夠屢次給出咱們的選項:

$ ./go_test.sh -a -a -a -a
-a was triggered!
-a was triggered!
-a was triggered!
-a was triggered!
$

最後一個例子讓咱們須要考慮到幾點:

  • 無效選項並不中止處理過程: 若是你想停掉腳本,你必須本身處理(在正確位置退出)
  • 多個相同選項是可行的: 若是你你不容許這麼作,你必須本身檢測(例如,設置一個變量或其餘方式)

一個帶參數的選項

讓咱們把上面的例子擴展一下。只有一點點:

  • -a如今須要一個參數-a now takes an argument
  • 遇到錯誤,解析過程以exit 1退出
#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

讓咱們繼續作和最後一個範例一樣的測試:

不用任何參數調用

$ ./go_test.sh
$

像上面同樣,什麼都沒發生。就沒觸發。

以非選項的參數調用

$ ./go_test.sh /etc/passwd
$

很是相似的狀況: 沒有觸發。

帶參數選項調用

非法選項:

$ ./go_test.sh -b
Invalid option: -b
$

和指望的同樣,像上面同樣,getopts不容許這個選項,和程序算法吻合。

合法選項,可是不帶強制要求的參數:

$ ./go_test.sh -a
Option -a requires an argument.
$

選項OK,可是丟掉了一個參數。

讓咱們提供這個參數:

$ ./go_test.sh -a /etc/passwd
-a was triggered, Parameter: /etc/passwd
$

參考資料

相關文章
相關標籤/搜索