2013-05-20 10 views
31

私は自分の.bash_profileで定義した関数の中でgetoptsを使用したいと思います。 考え方は、この関数にいくつかのフラグを渡して、その動作を変更したいと考えています。私はこのようにそれを呼び出すとBash関数内のgetoptsの使用

function t() { 
    echo $* 
    getopts "a:" OPTION 
    echo $OPTION 
    echo $OPTARG 
} 

:ここ

コードです

t -a bc 

私はこの出力を得る:

-a bc 
? 
  

間違っているのですか?手動でシフトして解析することなく値bcを取得したいと思います。関数内でgetoptsを正しく使用するにはどうすればよいですか?

EDITは:OK、私のシェルは、何らかの形で台無しにして、コードが細かいですが判明:無駄

EDIT#2に、OPTARG $をしようとする私のコードスニペットを修正しました。新しいウィンドウを開くとそれが解決されました。 argの値は実際$ OPTARGでした。

答えて

64

@Ansgarが指摘するように、あなたのオプションの引数は${OPTARG}に保存されているが、これは関数内でgetoptsを使用する際に注意する唯一のものではありません。また、${OPTIND}が関数に対してローカルであることを確認する必要があります。これを解除するか、localと宣言する必要があります。そうしないと、関数を複数回呼び出すと予期しない動作が発生します。

t.sh

#!/bin/bash 

foo() 
{ 
    foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; } 

    local OPTIND o a 
    while getopts ":a:" o; do 
     case "${o}" in 
      a) 
       a="${OPTARG}" 
       ;; 
      *) 
       foo_usage 
       ;; 
     esac 
    done 
    shift $((OPTIND-1)) 

    echo "a: [${a}], non-option arguments: $*" 
} 

foo 
foo -a bc bar quux 
foo -x 

例の実行:

$ ./t.sh 
a: [], non-option arguments: 
a: [bc], non-option arguments: bar quux 
foo: [-a <arg>] 

あなたが# local OPTINDをコメントアウトした場合、これはあなたの代わりに得るものです:

それ以外
$ ./t.sh 
a: [], non-option arguments: 
a: [bc], non-option arguments: bar quux 
a: [bc], non-option arguments: 

、その使用があります関数の外部で使用された場合と同じです。ここ

+7

できれば私はこの答えを100倍upvoteします。これは私を夢中にさせていた!! –

+0

1.) '1>&2'の' 1'は必要ありません。 2) 'a'、' o'、 'OPTARG'をローカルとして定義していませんでした。 3.) 'exit'はスクリプトを終了せず、サブシェルだけを終了します。スクリプトを終了するには、外側シェルで 'set -e'、サブシェルで' exit 1'を実行する必要があります。この例では問題は発生しませんが、 'MSG = $(foo ...)'がそれを行います。 – ceving

+0

@ceving 1)これはコーディングスタイルの問題ですが、いいえ、言語定義ごとに必要ではありません。 2)合意した、それらはローカルでなければなりません。 3)あなたが言ったように、私の例ではexit *がスクリプトを終了します。もちろん、 'exit'はサブシェルを終了しませんが、これはこの問題の特定の問題ではありません。あなたは 'set -e'を使う必要はないので、エラーを捕まえるだけでよく、' MSG = $(foo ...)|| 「死ぬ」も同様に機能する。 'set -e'はこの問題に対する一つの解決策ですが、他の多くの人たちと同じように使用することはお勧めしません(http://mywiki.wooledge.org/BashFAQ/105)。 –

4

引数は変数$OPTARGに格納されます。

function t() { 
    echo $* 
    getopts "a:" OPTION 
    echo $OPTION 
    echo $OPTARG 
} 

は出力:

$ t -a bc 
-a bc 
a 
bc
+0

で私が間違って私のコードスニペットを貼り付けた申し訳ありませんが...私も$ OPTARGをエコー、それが空白になって3行目です。他のアイデア? – Magnus

+0

@ Magnuおそらくあなたが関数を何度も呼び出していて、 '$ OPTIND'がローカルに定義されていないためです(Adrianの答えを参照)。あなたが私の答えを受け入れることに感謝していますが、むしろ代わりに彼を受け入れるべきです。 –

+0

コードはシェルに貼り付けるときにのみ機能しますが、スクリプトでは機能しません。 – kenorb

8

は、シェル関数内getopts使用の簡単な例である:

#!/usr/bin/env bash 
t() { 
    local OPTIND 
    getopts "a:" OPTION 
    echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG 
} 
t "[email protected]" 
t -a foo 

出力:@Adrian pointed outlocal OPTIND(又はOPTIND=1)として

$ ./test.sh -a bc 
Input: -a bc, OPTION: a, OPTARG: bc 
Input: -a foo, OPTION: a, OPTARG: foo 

シェルとして設定する必要が自動的OPTINDをリセットしませんmultiple calls to getoptsman bash)の間である。

getoptsのための基本構文は次のとおりです。

getopts OPTSTRING VARNAME [ARGS...] 

と、デフォルトでは、引数を指定しないと、明示的である「の$ @」とそれを呼び出すのと同じです:getopts "a:" opts "[email protected]"

問題の場合

、これらはgetoptsに使用される変数を確認するためである。

  • OPTIND - 次の引数へのインデックスを処理する、
  • OPTARG - 変数のための任意の引数に設定されていますオプションは、getopts
  • OPTERR(POSIXではありません) - 0または1に設定して、Bashがgetoptsによって生成されたエラーメッセージを表示するかどうかを示します。

さらにより、以下を参照してください。バッシュハッカーウィキ

+0

非常に慎重に答えを出しました。私はそれがうまくいくかどうかわかりませんが、素晴らしい仕事です。 – Drew

関連する問題