#!/usr/bin/perl
#
# getopts-template.pl
#
use Getopt::Std ;
sub usage_exit {
        print STDERR "Usage: getopts-template.pl [-a] [-d dir] item1 item2 ...\n" ;
        exit 1 ;
}
print "@ARGV\n" ;       ####DEBUG
{
        local $SIG{__WARN__} = \&usage_exit ;
        if (getopts("ad:h") != 1) {
                usage_exit ;
        }
}
if (defined $opt_h) {
        usage_exit ;
}
$argc = scalar @ARGV ;
print "\$argc=$argc\n" ;        ####DEBUG
print "\@ARGV=@ARGV\n" ;        ####DEBUG
print "\$opt_a=$opt_a\n" ;      ####DEBUG
print "\$opt_d=$opt_d\n" ;      ####DEBUG
要所だけ補足しますと、__WARN__ の行を書かない場合、未定義オプションを指定すると、Getopt::Std が自分でエラーメッセージ(Unknown option: x)を出してしまいます。
わたしは、この振る舞いは嫌なので、自分で用意した usage_exit を呼ぶようにしました。
もう1点、引数が必要なオプション -d dir について、dir が省略された場合にエラーにするには、getopts の戻り値を見る必要があります。getopts は、エラーが生じると、1 以外の値を返します。
実行結果は、次のようになります。
# ./getopts-template.pl -d dir item1 item2 -d dir item1 item2 $argc=2 @ARGV=item1 item2 $opt_a= $opt_d=dirbash の getopts と同じ振る舞いのようで、コマンドラインの後半でオプション指定を書くと、うまく処理できません。うーん、残念です。
# ./getopts-template.pl item1 item2 -d dir item1 item2 -d dir $argc=4 @ARGV=item1 item2 -d dir $opt_a= $opt_d=
2011-09-01追記
getopt(1) を使うテンプレートも作りました。次の記事も参照ください。
perl でオプション解析(getoptコマンド編)
2012-02-11追記
getopts の場合は、-ll のような複数回の指定を区別できないことを知りました。getopt(1) を使う方法ならば対応できますが、コードが長くなるのがいまひとつ。Getopt::Long を使うと、また、別のイライラに遭遇するようです。。。
2017-01-30追記
久々に、このパターンを CentOS 7 で使ったのですが、何やらごちゃごちゃと余計なメッセージが出ました。
[root@hoge tmp]# ./getopts-template.pl --help --help ./getopts-template.pl version [unknown] calling Getopt::Std::getopts (version 1.07 [paranoid]), running under Perl version 5.16.3. Usage: getopts-template.pl [-OPTIONS [-MORE_OPTIONS]] [--] [PROGRAM_ARG1 ...] The following single-character options are accepted: With arguments: -d Boolean (without arguments): -a -h Options may be merged together. -- stops processing of options. Space is not required between options and their arguments. [Now continuing due to backward compatibility and excessive paranoia. See 'perldoc Getopt::Std' about $Getopt::Std::STANDARD_HELP_VERSION.] $argc=0 @ARGV= $opt_a= $opt_d= [root@hoge tmp]#これはちょっと余計なお世話と思って、調べたところ、次のように追加の記述を行うことで、出なくなりました。
[root@hoge tmp]# diff -u getopts-template.pl getopts-template.pl-2017-01-30 
--- getopts-template.pl 2017-01-30 22:00:17.954554580 +0900
+++ getopts-template.pl-2017-01-30 2017-01-30 22:02:00.828239598 +0900
@@ -11,6 +11,8 @@
 }
 
 print "@ARGV\n" ; ####DEBUG
+sub HELP_MESSAGE { usage_exit ; }
+sub VERSION_MESSAGE { ; }
 {
  local $SIG{__WARN__} = \&usage_exit ;
  if (getopts("ad:h") != 1) {
[root@hoge tmp]# ./getopts-template.pl-2017-01-30 --help
--help
Usage: getopts-template.pl [-a] [-d dir] item1 item2 ...
[root@hoge tmp]# 
Simple is best. ですね。
0 件のコメント:
コメントを投稿