Hatena::ブログ(Diary)

(ひ)メモ このページをアンテナに追加 RSSフィード

2010-12-17 (Fri)

【あるあるおハマり大事典】シェル関数の中でgetopts使っておはまりの巻

シェル関数が定義されているこんなファイルsourceme.shがありました:

# sourceme.sh
getopts_in_function_nogood() {
  echo ">>getopts_in_function_nogood"
  server=

  while getopts "ns:" opt; do
    case $opt in
      n) echo "dry run";;
      s) server=$OPTARG;;
      ?) echo "unknown option" 1>&2; return;;
    esac
  done
  shift $(($OPTIND - 1))

  echo "server=$server"
}

新しいターミナルを立ち上げて、ロードして関数を実行してみます。

goa[~]$ . sourceme.sh
goa[~]$ getopts_in_function_nogood -n -s web
>>getopts_in_function_nogood
dry run
server=web

期待通りの動作です。が、続けてもいっかい同じのを実行してみると…

goa[~]$ !!
getopts_in_function_nogood -n -s web
>>getopts_in_function_nogood
server=

なんということでしょう!!! オプションが全く解釈されてません!!!!! 同じなのに!! なぞい!!!

で、man bashを読んでみるとこんな記述が。。。

OPTIND はシェルまたはシェルスクリプトが呼び出される度に 1 に初期化されます。オプションが引き数を必要とする場合には、 getopts はその引き数を変 数OPTARG に格納します。シェルが OPTIND を自動的に再設定することはありません。 1 つのシェルが呼び出されている間に別のパラメータの組合せを使う場合には、 getopts の呼び出しの間に手動で再設定を行わなければなりません

(ꏿ⌓ꏿ)

ということで、シェル関数でgetoptsを使うときはOPTINDを明に初期化しましょう。

getopts_in_function_good() {
  echo ">>getopts_in_function_good"
  server=

  OPTIND_OLD=$OPTIND
  OPTIND=1
  while getopts "ns:" opt; do
    case $opt in
      n) echo "dry run";;
      s) server=$OPTARG;;
      ?) echo "unknown option" 1>&2; return;;
    esac
  done
  shift $(($OPTIND - 1))
  OPTIND=$OPTIND_OLD

  echo "server=$server"
}

というわけで早速マイyasnippetのsh-mode/getoptsを更新しましたとさ。めでたしめでたし。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/hirose31/20101217/1292581425
2003 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 12 |
2012 | 01 | 02 | 03 | 06 | 08 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 |
2015 | 01 | 02 | 07 | 10 |
2016 | 01 | 05 | 10 | 12 |
2017 | 07 |