2011年7月5日火曜日

シェルスクリプトで最後の引数を取得したい

検証したのはKorn Shellだけど、bashやPOSIX準拠shでも動くはず。

最後の引数を取得するには、引数の数は$#に格納されているので、
$$#
とすればよさそうだが…?


!/bin/ksh
echo "Number of arg: $#"
echo "Value of last index: $$#"

(arg_test.sh)

実行すると
$ ./arg_test.sh a1 b2 c3 d4 e5
Number of arg: 5
Value of last index: 19401#
※本来はe5と出て欲しいのに…

考えて見れば分かるが、$$#はシェルが特殊変数$$と解析し、PIDを出力する。
さらに#が付いているので、リテラルとして追加してecho出力、となった。

エスケープすればいいのか?と思い、


echo "Value of last index: \$$#"


としてみても、
$ ./arg_test.sh a1 b2 c3 d4 e5
Number of arg: 5
Value of last index: $5
う~ん、もう少し。

いろいろ調べると、こういう時は組み込み関数evalを使えばいいらしい。


echo "Value of last index: `eval echo '$'$#`"


これでOK。
$ ./arg_test.sh a1 b2 c3 d4 e5
Number of arg: 5
Value of last index: e5
想定通り!


ただ、これだと引数が9個までならいいけれど、10個以上になるとうまく行かなくなってしまう。
$ ./arg_test.sh a1 b2 c3 d4 e5 f6 g7 h8 i9 j10 k11
Number of arg: 11
Value of last index: a11
これはeval echo '$'$#の中で$#が$11と置き換わったが、シェルスクリプトの引数は$1, $2, $3,...でアクセスできるが、$9までしかない。
$11は$1と1と解釈されたので、$1="a1"と"1"が出力されている。
10番目移行の引数にはshiftしていくか、${10}などとする必要がある。

なので、


echo "Value of last index: `eval echo '$'{$#}`"


にすれば
$ ./arg_test.sh a1 b2 c3 d4 e5 f6 g7 h8 i9 j10 k11
Number of arg: 11
Value of last index: k11
と10個を超えても大丈夫になった。

0 件のコメント: