2017-01-17 12 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 2'ではなく 'shift'と' esac'の後に '完了しました。フラグオプションはシフトを一切必要としません。一度に1つの引数をシフトするので、引数なしの '-b'を取り除くので、ループは終了します。つまり、getoptsの答えはより良い長期的な選択です。アドホックなソリューションは、アドホックなバグを取得します - あなたの無限ループ問題を目撃してください。 –

答えて

2

リストにある値の数を超えて移動しようとすると、shift nコマンドは何も行いません。これがコード内の無限ループの理由です。

getoptsを使用すると、多くの柔軟性が得られます。そうしないとあなたが入力する前に、$ 2の値を確認することができます

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

:あなたが常にあなたが最初の行を変えることができる2つのパラメータが必要と思われますので

#!/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

:そうでなければ、あなたはあなたのループをこのように書き換えることができ

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

これは、すべてのオプションが引数をとっている場合にのみ機能し、したがってそれらをペアとして扱うことができます。 – codeforester

1

引数が足りないためにシフトが失敗します。

しかし、すべてのエラー(set -e)でシェルが失敗するように設定すると、この問題はすぐに明らかになります。サイレント・エラーを避けることでデバッグを容易にし、規律とエラー・チェックを強制します。 set -uは、失敗した変数の展開でエラーを発生させ、非常に便利です。

関連する問題