当前位置: 首页 > news >正文

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设计实践》

http://www.jsqmd.com/news/585866/

相关文章:

  • OpenClaw镜像体验:30分钟玩转Qwen2.5-VL-7B多模态自动化
  • 开源模拟器性能优化指南:解决yuzu运行问题的系统方法
  • 魔兽争霸3兼容性终极解决方案:WarcraftHelper让你的经典游戏焕发新生
  • 【无人机路径规划】 K-means和遗传算法的无人机路径规划【含Matlab源码 15282期】
  • 3分钟找回遗忘QQ号:手机号查询工具让数字身份不再丢失
  • HsMod:突破炉石传说体验限制的终极模改解决方案
  • FPGA开发:按键消抖
  • 利用快马平台快速复现stm32cubemx配置,十分钟搭建stm32hal库项目原型
  • 免费开源神器drawio vs Processon:哪个更适合你的流程图需求?
  • 如何在Windows上快速掌握Poppler:5个实用技巧与场景应用终极指南
  • Ostrakon-VL-8B惊艳案例:自动识别价签脱落、倒置、模糊并生成修复工单
  • FanControl:动态平衡散热与静音的智能风扇管理方案
  • Blackbone手动映射技术:Windows内存操作库的终极指南
  • 深入解析GEM5与McPAT协同仿真:NoC功耗模型中Arbiter电容计算的微架构关联
  • 番茄小说下载器:打造个人离线图书馆的终极指南 [特殊字符]
  • nli-distilroberta-base安全部署考量:防范模型窃取、投毒攻击与数据泄露
  • AudioSeal部署案例:媒体集团AI内容中台集成AudioSeal实现全链路溯源
  • RHCA II之路---EX442-13
  • OCAuxiliaryTools:OpenCore高效管理与可视化配置全流程解决方案
  • 如何永久保存微信聊天记录?WeChatMsg完整数据守护指南
  • Navicat无限试用终极指南:一键解决14天限制的完整方案
  • 如何用Cats Blender插件实现模型优化与跨格式工作流简化
  • Java继承设计技巧:为什么你的sumAllArea方法不该声明为static?从PTA形状题看OOP原则
  • 如何快速使用网盘直链下载助手:告别限速困扰的完整指南
  • 深入解析Tencent Kona SM Suite:国密算法的架构设计与实践指南
  • 04:输出保留3位小数的浮点数
  • ag-grid cdn使用示例
  • PlugY插件:暗黑破坏神2单机模式的革命性增强解决方案
  • 别再手动对齐了!用Umeyama算法搞定激光SLAM与视觉SLAM的轨迹对齐(附Python代码)
  • 用Qwen3-Embedding-4B构建智能问答系统:快速部署,支持长文本理解