本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、bashのシェルスクリプト内でオプションを解析する「getopts」コマンドです。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、bashのシェルスクリプト内でオプションを解析する「getopts」コマンドです。
「getopts」は、bashのシェルスクリプト内でオプションを解析する際に役立つコマンドです。自作のシェルスクリプトで「-a」のような「ハイフン+アルファベット1文字」のオプションを扱う際に便利です。「-f ファイル名」のように引数を取るオプションも解析できます。
getoptsコマンドはbashのビルトインコマンド(内部コマンド、シェルコマンド)です。このため、「man」コマンドではなく、「help」コマンドや「man bash」で詳細を確認します。
シェルスクリプトのオプションを解析する他の方法もあります。まず、getoptsとよく似た名前で用途も同じ「getopt」コマンド(/usr/bin/getopt)があります。getoptコマンドはgetoptsとは異なり、「--」から始まるロングオプションも扱うことができます(連載第379回)。
この他、引数を1つずらす「shift」コマンドを使ってオプションを解析することも可能です。
getopts オプション文字列 変数名
※ [ ]は省略可能な引数を示しています。
getoptsにはオプションはありません。なお、オプション文字列の先頭に「:」記号を入れるかどうかによって、エラーメッセージ表示の有無を変更できます(本文を参照)。
getoptsでオプションを処理する際には、一般に「while文」と「case文」を組み合わせて使用します(※1)。
※1 opt1.shにあるwhile文については「シェルスクリプトに挑戦しよう(14)」を参照。case文については「シェルスクリプトに挑戦しよう(9)」を参照。
ここではスクリプト1を使って、getoptsの動作を見てみましょう。スクリプト1(opt1.sh)は、オプション「-a」「-b」「-c」を使用し、それぞれのオプションに応じてメッセージを表示します。
#! /bin/bash while getopts abc OPT do case $OPT in a) echo "[-a] が指定された";; b) echo "[-b] が指定された";; c) echo "[-c] が指定された";; *) echo "該当なし(OPT=$OPT)";; esac done
opt1.shの2行目にある「getopts abc OPT」の「abc」の部分は、利用するオプションの種類を指定しています。ここでは「-a」「-b」「-c」の3つです。続く「OPT」はgetoptsが解析した結果をセットする変数の名前で、case文で参照($OPT)しています。
画面1ではopt1.shの動作を確認しています。オプションを指定する際、「-a -b」のように個別に指定できる他、「-bc」のようにまとめて指定できることが分かります。さらに、getoptsで指定していないオプションが与えられた場合は、変数OPTに「?」という文字がセットされる様子も分かります。
getoptsに指定していないオプションを使用すると、画面1のように「不正なオプションです -- d」、あるいは「illegal option -- d」のようなメッセージを表示します。
このようなgetoptsのエラーメッセージを表示したくない場合は、「getopts :abc OPT」のように、オプション文字列の先頭に「:」記号を入れます。
スクリプト2(opt2.sh)では、先ほどのopt1.shの一部を書き換えて、独自のエラーメッセージを表示するようにしました。「OPTARG」という組み込み変数にはgetoptsが現在解析しようとしている文字列が入っています(※2)。abc以外のオプションを指定したとき、変数OPTには、解析結果である「?」という文字が入ります。
※2 getoptsコマンドでは、この他、2つの組み込み変数を利用できる。「OPTERR」はエラー出力を制御する変数で、初期値は1。値を0にすると「:」を付けたときと同様にエラー出力を抑制する。「OPTIND」は現在処理している引数の位置を表す。
#! /bin/bash while getopts :abc OPT do case $OPT in a) echo "[-a] が指定された";; b) echo "[-b] が指定された";; c) echo "[-c] が指定された";; *) echo "$OPTARGは定義されていません(OPT=$OPT)";; esac done
「-f ファイル名」のように、引数を取るオプションを解析したい場合は、スクリプト3(opt3.sh)のようにオプション文字の後に「:」記号を付けます。オプションの引数は、組み込み変数「OPTARG」で参照できます。
引数が必要なオプションに引数が指定されていなかった場合、解析結果として「:」という文字を保存します。定義されていないオプションの場合は、これまで同様「?」という文字を保存します。
#! /bin/bash while getopts :a:bc: OPT do case $OPT in a) echo "[-a] が指定された(引数=$OPTARG)";; b) echo "[-b] が指定された";; c) echo "[-c] が指定された(引数=$OPTARG)";; :) echo "$OPTARGに引数が指定されていません";; ?) echo "$OPTARGは定義されていません";; esac done
getoptsで引数付きのオプションを処理する際は、「スクリプトの実行時に引数とオプションが正しく指定されている」ことが前提になります。
例えば、opt3.shでは、「-a」と「-c」は引数が必要なため、「./opt3.sh -a 引数」あるいは「./opt3.sh -a 引数 -c 引数」のように「-a」と「-c」に引数が指定されていれば問題ありません。しかし、「./opt3.sh -a -b -c 引数」のように実行すると、「-a」の次に指定されている「-b」が「-a」の引数として扱われてしまい、その結果として、オプション「-b」が指定されていないことになってしまいます。
短いオプションでは、一般に引数を続けて書くことができます。従って、「-a」が引数を取らない場合は「-abc」が「-a」「-b」「-c」となるのに対し、「-a」が引数を取る場合は「-a」に対する引数「bc」として扱います。
シェルスクリプトに複雑なオプション指定が必要となった場合は、引数の先頭が「-」でないかどうかを確認するなど、他の方法でオプションを解析するか、用途別のシェルスクリプトに分割するといった対策を検討してください。
【加筆:2020年2月25日午後20時20分】本記事の公開後、スクリプト3の後「例えば、opt3.shでは……」とある段落の次に「短いオプションでは……」から始まる一段落を追加しました(編集部)。
西村 めぐみ(にしむら めぐみ)
元々はDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの"PCヘルパー"やピンポイント研修なども行っている。
Copyright © ITmedia, Inc. All Rights Reserved.