如何通过命令行开关为我的Perl程序启用调试模式?
我正以“头脑优先”的方式学习Perl.我绝对是这种语言的新手:
我试图从CLI调用debug_mode,通过“打开和关闭”某些子程序来控制我的脚本的工作方式. 以下是我到目前为止所得到的: #!/usr/bin/perl -s -w # purpose : make subroutine execution optional,# which is depending on a CLI switch flag use strict; use warnings; use constant DEBUG_VERBOSE => "v"; use constant DEBUG_SUPPRESS_ERROR_MSGS => "s"; use constant DEBUG_IGNORE_VALIDATION => "i"; use constant DEBUG_SETPPING_COMPUTATION => "c"; our ($debug_mode); mainMethod(); sub mainMethod # () { if(!$debug_mode) { print "debug_mode is OFFn"; } elsif($debug_mode) { print "debug_mode is ONn"; } else { print "OMG!n"; exit -1; } checkArgv(); printErrorMsg("Error_Code_123","Parsing Error at..."); verbose(); } sub checkArgv #() { print ("Number of ARGV : ".(1 + $#ARGV)."n"); } sub printErrorMsg # ($error_code,$error_msg,..) { if(defined($debug_mode) && !($debug_mode =~ DEBUG_SUPPRESS_ERROR_MSGS)) { print "You can only see me if -debug_mode is NOT set". " to DEBUG_SUPPRESS_ERROR_MSGSn"; die("terminated prematurely...n") and exit -1; } } sub verbose # () { if(defined($debug_mode) && ($debug_mode =~ DEBUG_VERBOSE)) { print "Blah blah blah...n"; } } 据我所知,至少它有效……: > -debug_mode开关不会干扰正常的ARGV > ./optional.pl 但是,当多个debug_modes“混合”时,我很困惑,例如: > ./optional.pl -debug_mode = sv 我不明白为什么上面的代码行“神奇地起作用”. 我看到“DEBUG_VERBOS”和“DEBUG_SUPPRESS_ERROR_MSGS”都适用于脚本,在这种情况下这很好. 但是,如果存在一些“冲突”的调试模式,我不确定如何设置“debug_modes的优先级”? 另外,我不确定我的方法对于Perlists是否足够好,我希望我能够朝着正确的方向前进. 一个最大的问题是我现在把if语句放在里面 我知道必须有来自CPAN或其他地方的调试模块,但我想要一个真正的最小解决方案,它不依赖于除“默认”之外的任何其他模块. 而且我无法控制执行此脚本的环境…… 解决方法
要处理命令行选项,请查看
Getopt::Long.您将获得各种灵活的参数解析选项.
有许多模块可以处理日志记录. Log4Perl是一个非常流行的记录模块. 如果你真的,真的想通过避免CPAN来限制自己(这是一个坏主意),你可以很容易地将一个记录模块放在一起. 这是我为你砍的一小部分.它需要测试和真实的文档等等.我还使用了一些高级技术,比如自定义import()方法.围绕我使用单个变量来存储整个应用程序的DEBUG设置也存在一些问题.但它的确有效.我在一个项目中使用了类似的模块,并对它非常满意. package QLOG; use strict; use warnings; use Carp qw(croak); our %DEBUG_OPTIONS; our %VALID_DEBUG_OPTIONS; our %DEBUG_CONFLICTS; sub import { my $pkg = shift; my $target = caller(); my %opts = @_; # Configure options croak "Must supply an array ref of valid modes" unless exists $opts{options}; @VALID_DEBUG_OPTIONS{ @{$opts{options}} } = (); # Configure conflicts if( exists $opts{conflicts} ) { @DEBUG_CONFLICTS{ keys %{$opts{conflicts}} } = values %{$opts{conflicts}} } # Export DEBUG method { no strict 'refs'; *{$target.'::DEBUG'} = &;DEBUG; } return; } sub DEBUG { my $mode = shift; croak "DEBUG mode undefined" unless defined $mode; return unless ( $mode eq 'ANY' and %DEBUG_OPTIONS ) or exists $DEBUG_OPTIONS{$mode}; warn "$_n" for @_; return 1; } sub set_options { for my $opt ( @_ ) { die "Illegal option '$opt'" unless exists $VALID_DEBUG_OPTIONS{$opt}; $DEBUG_OPTIONS{$opt}++; } return; } sub check_option_conflicts { for my $opt ( keys %DEBUG_OPTIONS ) { if (exists $DEBUG_CONFLICTS{$opt}) { for ( @{$DEBUG_CONFLICTS{$opt}} ) { die "Debug option $opt conflicts with $_" if exists $DEBUG_OPTIONS{$_} } } } return; } 1; 然后像这样使用它: #!/usr/bin/perl use strict; use warnings; use Getopt::Long; use QLOG options => [qw( VERBOSE SUPPRESS_ERROR_MSGS IGNORE_VALIDATION SETPPING_COMPUTATION )],conflicts => { VERBOSE => [qw( SUPPRESS_ERROR_MSGS SETPPING_COMPUTATION )],}; process_args(); DEBUG VERBOSE => 'Command line data parsed.'; main(); ### --------------- sub main { DEBUG VERBOSE => 'BEGIN main()'; if( DEBUG 'ANY' ) { print "debug_mode is ONn"; } else { print "debug_mode is OFFn"; } warn "Error which could be surpressedn" unless DEBUG 'SUPPRESS_ERROR_MSGS'; } # Get arguments and process flags like 'v' and 'sc' into strings specified # in QLOG configuration above. # This processing makes the nice DEBUG VERBOSE => 'blah'; syntax work. sub process_args { # Use Getopt::Long to parse @ARGV my @debug_options; GetOptions ( 'debug-options=s@' => @debug_options,'help' => &;usage,) or usage(); # Convert option flags to strings. my %option_lut = qw( v VERBOSE s SUPPRESS_ERROR_MSGS i IGNORE_VALIDATION c SETPPING_COMPUTATION ); my @options = map { # This chained map exists $option_lut{$_} # looks in the lut for a flag ? $option_lut{$_} # translates it if found : $_ # or passes on the original if not. } map { # Here we split 'cv' into ('c','v') split // } @debug_options; # Really should use Try::Tiny here. eval { # Send a list of strings to QLOG # QLOG will make sure they are allowed. QLOG::set_options( @options ); QLOG::check_option_conflicts(); 1; # Ensure true value returned if no exception occurs. } or usage($@); return; } sub usage { my $message = shift || ''; $message = '' if $message eq 'help'; print <<"END"; $message Use this proggy right. END exit; } 您可能希望添加一个方法以使您的调试消息可以抑制. 就像是: sub SUPPRESSED_BY { my $mode = shift; return if exists $DEBUG_OPTIONS{$mode); return @_; } 导出符号然后使用它: DEBUG VERBOSE => SUPPRESSED_BY SUPPRESS_ERRORS => 'My message here'; 将日志记录模块放在一起的容易性导致存在大量可用的这种模块.有很多方法可以完成这项任务,并且在检测代码时需要有不同的变化,甚至更多.我甚至编写了一些记录模块来满足各种需求. 无论如何,当你首先潜入Perl时,这应该会给你一个严重的扣篮. 随意问我’到底是什么?’输入问题.我意识到我在向你扔了很多东西. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |