コマンド引数の処理を楽にする
みなさんPerl書いてますか?
今回は、「コマンド引数の処理を楽にする」モジュールをご紹介します。
使用するモジュールは、Getopt::Kingpin
です。
Getopt::Kingpin
入ってない方は、cpanm -v Getopt::Kingpin
でインスコしましょう。
便利なこと
このモジュールを使うと下記の様な処理が楽にできます。
- フラグ・引数の定義
- ショートフラグの設定
- 値の形式をチェック(string, int)
- 必須項目の設定
- デフォルト値の設定
- 指定ファイルの有無チェック
- サブコマンドの設定
-
--help
の自動生成
などなど・・・
すべては紹介できませんが、よく使うものを中心にご紹介していきます。
フラグ・引数の定義
まずは、フラグと引数の定義からやってみましょう。
フラグ「piyo」と引数「fuga」を定義したプログラムを用意します。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->string;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->string;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
# 値を取得
printf "flag: %s\n", $piyo->value;
printf "arg : %s\n", $fuga->value;
フラグと引数を指定してプログラムを実行すると・・・
$ perl hoge.pl --piyo aaa bbb
flag: aaa
arg : bbb
取得できました。
ショートフラグの設定
ショートフラグの設定も簡単です。
flag
で定義したものに対してshort('x')
を指定するだけ!
flag('xxx', 'xxxxx')->short('x')->string;
先程の--piyo
を-p
でも処理できるようにすると
my $piyo = $kingpin->flag('piyo', 'piyo desu')->short('p')->string;
こんな感じですね。
$ perl hoge.pl --p aaa bbb
flag: aaa
arg : bbb
$ perl hoge.pl --piyo aaa bbb
flag: aaa
arg : bbb
上記のどちらでも同じ指定したことになります。
値の形式をチェック
値の形式を指定することもできます。
# フラグ
flag('xxx', 'xxxxx')->string;
flag('xxx', 'xxxxx')->int;
# 引数
arg('xxx', 'xxxxx')->string;
arg('xxx', 'xxxxx')->int;
フラグ・引数を解析するときに、指定した形式かチェックしてくれます。
先程のコードを変更して、フラグと引数を「string」→「int」に変更して試してみましょう。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->int;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->int;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
$ hoge.pl --piyo aaa bbb
int parse error
必須項目の設定
必ず指定してほしいフラグ・引数には、required()
を設定すると指定しなかったらエラーとなり処理を止めることができます。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->required->string;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->required->string;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
--piyo
(required)を指定しなかった場合
$ hoge.pl bbb
hoge.pl: error: required flag --piyo not provided, try --help
デフォルト値の設定
デフォルト値の設定も簡単です。
default('xxx')
を使用します。
# フラグ
flag('xxx', 'xxxxx')->default('aaa')->string;
# 引数
arg('xxx', 'xxxxx')->default('bbb')->string;
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->default('piyopiyo')->string;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->default('fugafuga')->string;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
# 値を取得
printf "flag: %s\n", $piyo->value;
printf "arg : %s\n", $fuga->value;
実行時、何も指定してなかったらデフォルト値が使用されます。
$ perl hoge.pl
flag: piyopiyo
arg : fugafuga
指定ファイルの有無チェック
ファイルやディレクトリを指定するようにした場合、エラーチェックを書かなければいけませんよね。
それもGetopt::Kingpin
に任せちゃいましょう。
下記のような関数が用意されています。
-
existing_file
- 存在するファイル
-
existing_dir
- 存在するディレクトリ
上記の形式としてフラグ・引数を指定した場合は、
解析時にファイル・ディレクトリの存在有無をチェックしてくれます。
ちなみにvalue()
はPath::Tiny
な形で返してくれるので、
あとは煮るなり焼くなりは好きにできますね。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->existing_file;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->existing_dir;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
my $piyo_file = $piyo->value;
my $fuga_dir = $fuga->value;
$ perl hoge.pl --piyo piyo.txt fuga_dir
error: path 'piyo.txt' does not exist, try --help
$ perl hoge.pl --piyo piyo.txt fuga_dir
error: path 'fuga_dir' does not exist, try --help
存在しないファイルを指定したい場合は、file()
を使用できます。
こちらもPath::Tiny
な形で返してくれます。
flag('xxx', 'xxxxx')->file
サブコマンドの設定
サブコマンドの設定も簡単です。
Getopt::Kingpin
オブジェクトに対して、command()
を使用します。
サブコマンドのフラグ・引数の定義に関しても、同じように定義していくだけです。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# サブコマンド「aaa」
my $aaa = $kingpin->command('aaa', 'aaa command desu');
# サブコマンド「aaa」 - フラグ(flag)の定義
my $piyo = $aaa->flag('piyo', 'piyo desu')->string;
# サブコマンド「aaa」 - 引数(arg)の定義
my $fuga = $aaa->arg('fuga', 'fuga desu')->string;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
if ($cmd eq "aaa") {
# サブコマンド「aaa」のとき
printf "subcommand: aaa\n";
printf "flag: %s\n", $piyo->value;
printf "arg : %s\n", $fuga->value;
}
下記のように実行できます。
$ perl hoge.pl aaa --piyo ppp bbbb
subcommand: aaa
flag: ppp
arg : bbb
--helpの自動生成
フラグや引数の説明を表示するようにするのって処理やメンテも大変ですよね・・・
kingpinの場合は、フラグや引数のときに説明をかけるようになっているので
定義するだけで--help
ができちゃうのです。
use strict;
use warnings;
use utf8;
use Getopt::Kingpin;
my $kingpin = Getopt::Kingpin->new;
# フラグ(flag)の定義
my $piyo = $kingpin->flag('piyo', 'piyo desu')->string;
# 引数(arg)の定義
my $fuga = $kingpin->arg('fuga', 'fuga desu')->string;
# フラグ・引数を解析
my $cmd = $kingpin->parse;
# 値を取得
printf "flag: %s\n", $piyo->value;
printf "arg : %s\n", $fuga->value;
--help
を実行してみると・・・
$ hoge.pl --help
usage: hoge.pl [<flags>] <fuga>
Flags:
--help Show context-sensitive help.
--piyo=PIYO piyo desu
Args:
[<fuga>] fuga desu
ね、簡単でしょ?
ショートフラグ(-h
)でも使用したいという方は、
下記の処理を追加すればいけます。
$kingpin->flags->get("help")->short('h');
まとめ
引数処理するときは、Getopt::Kingpin
を使って楽に処理しましょう!