2017-01-17 24 views
0

我有一個循環來解析命令行參數。如果-d或-b參數有一個參數,一切工作正常。但是當我傳遞沒有參數的-d或-b時,腳本進入無限循環。Bash參數解析邏輯運行到無限循環

# Parse command line input 
while [ "$#" -gt 0 ]; do 
    case "$1" in 
    -d) DOMAIN="$2"; shift 2;; 
    -b) BITS="$2"; shift 2;; 
    *) die "unrecognized argument: $1" 
    esac 
done 

如何在空參數上拋出錯誤?

+3

如果您的參數只是單個字母,您可以使用['getopts'](https://www.gnu.org/software/bash/manual/bashref.html#index-getopts),而不是滾動自己的。 –

+1

一個可行的技巧,特別是如果你有一些標誌選項(不帶參數),在'case'內部是'shift'而不是'shift 2',而'esac'後面是'shift',' done'。旗幟選項根本不需要轉換。因爲它會一次移動一個參數,所以它會擺脫一個沒有參數的'-b',所以循環會終止。也就是說,'getopts'答案是更好的長期選擇。臨時解決方案獲取臨時錯誤 - 見證你的無限循環問題。 –

回答

2

如果嘗試移動多於列表中存在的值,shift n命令不會執行任何操作。這就是代碼中無限循環的原因。

使用getopts是正確的選擇,因爲它爲您提供了很大的靈活性。否則,你可以這樣改寫你的循環:

#!/bin/bash 
# Parse command line input 
d_flag=0 
b_flag=0 
while [ "$#" -gt 0 ]; do 
    case "$1" in 
    -d) 
     d_flag=1 
     shift 
     [[ $1 == -* ]] && continue # argument to -d not given 
     DOMAIN=$1 
     shift 
     ;; 
    -b) 
     b_flag=1 
     shift 
     [[ $1 == -* ]] && continue # argument to -b not given 
     BITS=$1 
     shift 
     ;; 
    *) echo "unrecognized argument: $1"; exit 2;; 
    esac 
done 

if [[ $d_flag = 1 && -z $DOMAIN ]]; then 
    # handle error - option requires an argument 
fi 

if [[ $b_flag = 1 && -z $BITS ]]; then 
    # handle error - option requires an argument 
fi 
0

因爲它似乎你總是需要兩個參數,你可以第一行更改爲:

while [ "$#" -eq 2 ]; do 

否則,你可以檢查$ 2,進入前值這樣的循環:

if [[ -z $2 ]]; then 
echo "missing second parameter" 
else 
#do the while loop 
fi 
+0

只有當我們有所有選項進行爭論時,這纔會起作用,因此我們可以將它們視爲成對。 – codeforester

1

由於參數不夠,轉換失敗。

然而,這個問題會立即顯而易見是你設置你的shell失敗的所有錯誤(與set -e)。在許多情況下,它通過避免無聲故障使得調試更容易,並且執行紀律和錯誤檢查。 set -u在失敗的變量擴展中導致錯誤,也非常有用。