Perl:命令行参数的处理
相关阅读Perl专栏https://blog.csdn.net/weixin_45791458/category_12190090.html命令行参数是shell和perl交互的一个重要媒介本文介绍了如何在Perl中对命令行参数进行处理。首先我们给出所有的源程序再分别对其中的各个子例程进行讲解。sub print_and_exit { print _, \n; exit 1; } # print_and_exit sub read_argv { my ($aref, $hv) _; my ($opt); for my $arg ( $aref ) { if ( $arg ~ /^-/ ) { $opt $arg; if ( exists $hv-{$opt} ) { print_and_exit( Repeated option: $arg ); } else { { $hv-{$opt} } (); } } elsif ( defined $opt ) { $arg ~ s/^\s*// ; push { $hv-{$opt} }, $arg; } else { print_and_exit( Un-support option: $arg ); } } } # read_argv sub check_argv_perl_type { my ($hr, $hv) _; for my $opt ( keys %$hv ) { if ( exists $hr-{$opt} ) { if ( ${$hr-{$opt}}{perl_type} eq scalar) { if ( { $hv-{$opt} } ! 1 ) { print_and_exit( Error: only one parameter is expected to $opt ); } } elsif ( ${$hr-{$opt}}{perl_type} eq array) { if ( { $hv-{$opt} } 1 ) { print_and_exit( Error: one or more parameter is expected to $opt ); } } else { print_and_exit( Error: unknown perl_type of $opt ); } } else { print_and_exit( Un-support option: $opt ); } } } # check_argv_perl_type sub check_argv_data_type { my ($hr, $hv) _; for my $opt ( keys %$hv ) { if ( exists $hr-{$opt} ) { next unless exists $hr-{$opt}{data_type}; if ( $hr-{$opt}{data_type} eq inputfile) { for my $arg ( { $hv-{$opt} } ) { if ( ! ( (-f $arg) and (-s $arg) ) ) { print_and_exit( Error: input file is expected to $opt: $arg ); } } } elsif ( $hr-{$opt}{data_type} eq num) { for my $arg ( { $hv-{$opt} } ) { unless ( ( $arg ~ /^-?\d$/ ) or ( $arg ~ /^-?\d\.\d$/ ) or ( $arg ~ /^-?\d[eE]-?\d$/ ) or ( $arg ~ /^-?\d\.\d[eE]-?\d$/ ) ) { print_and_exit( Error: number is expected to $opt: $arg ); } } } elsif ( $hr-{$opt}{data_type} eq inputdir) { for my $arg ( { $hv-{$opt} } ) { if ( ! -d $arg ) { print_and_exit( Error: directory is expected to $opt: $arg ); } } } } else { print_and_exit( Un-support option: $opt ); } } } # check_argv_data_type sub get_default { my ($hr, $hv) _; for my $opt ( keys %$hr ) { next if exists $hv-{$opt} ; if ( exists $hr-{$opt}{default} ) { ### default some_scalar, OR default [some, element, of, array], $hv-{$opt} $hr-{$opt}{default}; } else { print_and_exit( Error: no input or default for $opt ); } } } # get_default sub combine_scalar { my ($hr, $hv) _; for my $opt ( keys %$hv ) { if ( ${$hr-{$opt}}{perl_type} eq scalar) { $hv-{$opt} $hv-{$opt}-[0]; } } } # combine_scalar sub Handle_argv { my ($aref, $hr, $hv) _; read_argv($aref, $hv); check_argv_perl_type($hr, $hv); check_argv_data_type($hr, $hv); get_default($hr, $hv); combine_scalar($hr, $hv); } # Handle_argv sub print_argv { my ($hv) _; for my $opt ( keys %$hv ) { print $opt ; for my $pv ( { $hv-{$opt} } ) { print $pv; } print \n; } } # print_argv my %rule_of_opt ( -s { perl_type scalar, data_type inputfile, }, -a { perl_type array, data_type num, default 5 } ); my (%value_of_opt) ; Handle_argv( \ARGV, \%rule_of_opt, \%value_of_opt ); print_argv( \%value_of_opt ); exit 0;1、print_and_exit该子例程用于根据参数打印信息并使用exit退出程序。2、read_argv该子例程用于将命令行参数读进参数散列中。参数散列的键为命令行参数中各个选项如-s和-a值为命令行参数中跟在该选项后的参数在这里规定属于一个选项的参数是该选项后至下一个选项间的参数且选项不能重复否则会报错Repeated option因为属于一个选项的参数可能有多个需要用数组保存所以使用$hv-{$opt}保存了一个指向数组的引用注意Perl中数组的值和散列的值必须是标量(scalar)。使用push将选项的参数值加入该选项对应值数组引用指向的数组中。3、check_argv_perl_type该子例程用于检查read_argv所读取的散列中每个选项的参数数量是否符合散列%rule_of_opt所定义的规则在代码中-s选项的perl_type属性为标量而-a选项的perl_type属性为数组。如果不符合则程序会报错提示参数数量有问题并退出。4、check_argv_data_type该子例程用于检查read_argv所读取的散列中每个选项的参数类型是否符合散列%rule_of_opt所定义的规则在代码中-s选项的data_type属性为输入文件而-a选项的perl_type属性为数字。如果不符合则程序会报错提示参数类型有问题并退出。代码中使用了正则表达式对数字进行识别使用文件操作符-f和-d分别对文件和目录进行识别有关Perl中正则表达式的内容可以看Perl正则表达式。5、get_default该子例程用于在未指定选项时为其创建默认参数值默认值可以根据规则是标量或数组如果一个选项没有出现且没有默认值则会报错。6、combine_scalar该子例程用于对只有一个参数的选项进行优化会直接使用$hv-{$opt}保存该参数值而不是保存指向数组的引用。7、Handle_argv这是将子例程整合封装的例程注意各子例程的调用顺序。8、print_argv该子例程可以打印经过处理后的选项参数散列用于观察结果。源代码来源于《Pelr语言IC设计实践》