getoptsコマンドでオプションを使ったシェルプログラミングは楽しい♪
こぬつわ。
ほってぃ~ぬです┌(┌ ┌ ┌ ┌ ^ω^)」
ソーシャルアプリ事業部でエンジニアをやっています。
今回はぼくが記事を書く順番という事で、
今まで写メってきた秘伝のねこ画像を掲載しようとしましたが
【もっと知的な内容の記事を書け!】とブログ管理者に怒られましたので
シェルプログラミングの事でも書こうと思います。
あとでブログ管理者の自宅サーバにDOS攻撃でも仕掛けてやろうかしら(プンプン。
シェルプログラミングは本当に楽しいです。
知ってるかも知れませんが
getoptsコマンドでオプションを取り扱う方法を紹介したいと思います。
簡単な書式としては
getopts 【許可するオプション】 【任意の変数名】
許可するオプションが複数ある際はスペースを開けずに並べて書き、
オプションの引数を取得する場合は : を続けて書きます。
例えば -aオプションと -bオプションを受け取りたい、-bオプションに関しては値も受け取りたいという場合は、下記のように書きます。
[sourcecode lang=”text”]getopts ab: opts[/sourcecode]
そしてgetoptsを実行する度に左からひとつずつオプションがパースされていきます。
オプションが存在する場合は【任意の変数名】にオプション名が入ります。この場合は$optsですね。
オプションの引数を受け取る事を許可した場合は$OPTARGという変数に値が順に上書きされていきます。
getoptsはパースするオプションが尽きると(もしくは最初から指定されたオプションが存在しないと)、0より大きいリターンコードを吐きます。
ここがポイントです。
正常終了ではないのです。
いちいちオプションの数だけgetoptsしてたらソースが長くなってしまうし面倒ですよね。
そこでgetoptsを使用する時はこれを利用してwhile文をかませると便利です。
サンプルのコードを書いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[sourcecode lang="text"]#!/bin/bash while getopts ab: opt do case $opt in a) a=1 ;; b) b=1 b_value=$OPTARG ;; esac done echo "-a: $a" echo "-b: $b" echo "-b_value: $b_value"[/sourcecode] |
このファイルをtest.shとしたらコマンドラインで下記のように打ってみます。
1 |
[sourcecode lang="text"]./test.sh -ab sonicmoov[/sourcecode] |
結果は・・・
1 2 3 |
[sourcecode lang="text"]-a: 1 -b: 1 -b_value: sonicmoov[/sourcecode] |
ばっちりオプションを受け取れていますね!
では今度は-bオプション無しで実行してみます。
1 |
[sourcecode lang="text"]./test.sh -a[/sourcecode] |
1 2 3 |
[sourcecode lang="text"]-a: 1 -b: -b_value:[/sourcecode] |
-aオプションだけ受け取れていますね。
これらはサブシェルでの実行でしたから
今度はドットコマンドを使ってカレントシェルで実行します。
1 |
[sourcecode lang="text"]. test.sh -ab sonicmoov[/sourcecode] |
1 2 3 |
[sourcecode lang="text"]-a: 1 -b: 1 -b_value: sonicmoov[/sourcecode] |
ふむ、何も問題なさそうですね。
じゃあ今度はオプション無しで実行してみます。
1 |
[sourcecode lang="text"]. test.sh[/sourcecode] |
結果は・・・
1 2 3 |
[sourcecode lang="text"]-a: 1 -b: 1 -b_value: sonicmoov[/sourcecode] |
!!(・ω・)
オプション無しにも関わらず値が入っています。
シェル変数を確認してみると・・・
1 |
[sourcecode lang="text"]declare[/sourcecode] |
1 2 3 |
[sourcecode lang="text"]a=1 b=1 b_value=sonicmoov[/sourcecode] |
前に実行した時のシェル変数が既に入ったままです。
これではオプション無しで実行してもオプションありとして扱われ
重要な処理をしているバッチなどでは非常に危険です。
バッチ内でシェル変数を初期化していれば回避できる問題ですがそういう処理があるとは限りません。
だからオプションを取り扱っているシェルスクリプトを実行する際はサブシェルで実行するのが好ましいと思います。
親シェルのシェル変数はexportしてない限り子シェルには引き継がれませんからね!
次回の番まで僕が生きていたらまたシェルの事を書こうと思います。
それでは~ ┌(┌ ┌ ┌ ┌ ^ω^)ノシ