2011-10-05 16 views
9

私は、bashスクリプトがオプションとスイッチ(ロングオプションとショート-oフォームの両方)を処理できるように、getoptgetopsではなく)を使用しています。getopt無効なオプションを無効にする

無効なオプションをトラップして処理することができます。通常、ユーザーはcmd --helpを試してからスクリプトを終了する必要があります。 「: - 『X』に無効なオプションをgetoptは」ここ

は私が私のgetoptを設定するために使用している模様だ

シングは、無効なオプションは、それ自体のようなメッセージを出力しているgetoptは、によって捕捉されていますパラメータ:

set -- $(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "[email protected]") 

ここで、$ LONG_OPTIONSと$ SHORT_OPTIONSの両方は、カンマ区切りのオプションリストです。ここで

は、私はオプションを処理扱う方法は次のとおりです。

while [ $# -gt 0 ] 
    do 
     case "$1" in 
      -h|--help) 
       cat <<END_HELP_OUTPUT 

    Help 
    ---- 

    Usage: ./cmd.sh 

    END_HELP_OUTPUT 

       shift; 
       exit 
       ;; 
      --opt1) 
       FLAG1=true 
       shift 
       ;; 
      --opt2) 
       FLAG2=true 
       shift 
       ;; 
      --) 
       shift 
       break 
       ;; 
      *) 
       echo "Option $1 is not a valid option." 
       echo "Try './cmd.sh --help for more information." 
       shift 
       exit 
       ;; 
     esac 
    done 

getopt -qは出力を抑制しますが、caseステートメント内の私のトラップ方式は、まだ私が期待するものを行うことができません。代わりに、無効な引数にもかかわらず、プログラムはただ実行します。

答えて

8

Thisソートは、私の作品:

params="$(getopt -o d:h -l diff:,help --name "$cmdname" -- "[email protected]")" 

if [ $? -ne 0 ] 
then 
    usage 
fi 

eval set -- "$params" 
unset params 

while true 
do 
    case $1 in 
     -d|--diff) 
      diff_exec=(${2-}) 
      shift 2 
      ;; 
     -h|--help) 
      usage 
      exit 
      ;; 
     --) 
      shift 
      break 
      ;; 
     *) 
      usage 
      ;; 
    esac 
done 
+0

*)に達しましたか? – jarno

+0

@jarno 'case'文と' getopt'呼び出しの間に不一致があると、そこに捕捉されます。それは単に守備的なプログラミングです。 – l0b0

0

私はこれが助けることができるかどうかわからないんだけど、のgetopt(1)のgetoptを使用しています(3)と私が正しくoptstringにの拳のキャラクターならば報告のgetopt(3)抑制エラーを思い出した場合はコロンです。スタイルの

+0

':' optstringの内の最初の文字が抑制されるようメッセージ出力。しかし、getopt(1)の戻りコードはまだ0ではなく、認識できないオプションはgetopt(1)によって出力されません。 –

1

これは最も堅牢なソリューションではありませんが、それが合理的です。それは次のように依存しています:

  • getoptプリントは「getoptは:」が付いていることをエラーメッセージ
  • 仮定はそれが増大し、getoptのエラーメッセージのクリーンアップバージョンを通過するように許容可能だということですカスタム情報付き。

コードスニペット:

# Invoke getopt; suppress its stderr initially. 
args=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "[email protected]" 2>/dev/null) 
if [[ $? -ne 0 ]]; then # getopt reported failure 
    # Rerun the same getopt command so we can capture stderr output *only* this time. 
    # Inefficient (and a potential maintenance headache, if literals were involved), but this will only execute in case of invalid input. 
    # Alternatively, redirect the first getopt invocation's stderr output to a temp. file and read it here. 
    errmsg=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "[email protected]" 2>&1 1>&-) 
    # Strip getopt's prefix and augment with custom information. 
    echo -e "${errmsg#getopt: }\nTry './cmd.sh --help for more information." 1>&2 
    exit 1 
fi 
+0

うまくいくのでしょうか?あなたが言ったように、かなり壊れやすい。 –

+0

@TomAuger:「かなり壊れやすい」とは、「最も堅牢ではありませんが、合理的です」と言い換えると、互換性のない英語のシェルを実行している必要があります。常に、getoptから情報を取得しようとすると、プログラマチックに報告するようには設計されていないということが難しくなります。つまり、stderrの出力が最初に来ると仮定することについての部分は実際には不安定なので、私はそれに対処するコードを改訂しました。単一のコマンド実行(一時ファイルの明示的な作成を伴わない)からstdoutとstderrを別々の変数に取り込む方法を教えてください。 – mklement0

1

はあなたがすべてではgetoptを使用する必要がありますか?あなただけの場合

while [ $# -gt 0 ]; do 
    case "$1" in 
    -d|--diff) 
     diff_exec=(${2-}) 
     shift 
     ;; 
    -h|--help) 
     usage 
     exit 
     ;; 
    --) 
     break 
     ;; 
    *) 
     usage 
     ;; 
    esac 
    shift 
done 

コードをチェックしています。

1

私は、これはgetoptsはcase文の最後の項目として作用することが分かっ:

*)evalのエコー "認識できないのarg \ $$ [OPTIND-1]"。使用法;出口 ;;

0

私が使用したコマンドライン解析です。欠けているオプションやパラメータを処理するために、解析ロジックを増やすことで改善することができます。

コマンドラインについて

:使用BB -C CC -b -a AA、結果S/BA = AAのB = BBのC = CC

OPT=("[email protected]") # Parses the command line into words. 

for [[ I=0;I<${#OPT[@]};I++ ]] 
    do 
     case "${OPT[$I]}" in   
     -a) a=${OPT[$I+1]} ;;   
     -b) b=${OPT[$I+1]} ;;   
     -c) c=${OPT[$I+1]} ;;  
     esac 
    done 
関連する問題