GetoptLong未对缺失的REQUIRED_ARGUMENT报错,如何触发必填参数错误?
问题描述
测试发现GetoptLong的错误仅在调用.each方法时触发,而非构造函数阶段:
仅初始化GetoptLong实例时,即使传入不完整的必填参数也不会报错:
require "getoptlong" GetoptLong.new( [ "--argument", "-a", GetoptLong::REQUIRED_ARGUMENT ] ) # 执行命令:ruby script.rb --argument # 无报错输出
但调用.each方法时,不完整的必填参数会触发错误:
require "getoptlong" GetoptLong.new( [ "--argument", "-a", GetoptLong::REQUIRED_ARGUMENT ] ).each # 执行命令:ruby script.rb --argument # 触发错误: # test_getoptlong.rb: option `--argument' requires an argument # /Users/me/.rbenv/versions/3.1.1/lib/ruby/3.1.0/getoptlong.rb:398:in `set_error': option `--argument' requires an argument (GetoptLong::MissingArgument)
如果完全不传入--argument参数,即使调用.each也不会报错:
require "getoptlong" GetoptLong.new( [ "--argument", "-a", GetoptLong::REQUIRED_ARGUMENT ] ).each # 执行命令:ruby script.rb # 无错误输出
由于该参数被设置为GetoptLong::REQUIRED_ARGUMENT,期望在未传入该参数时触发错误,请问如何实现当任意GetoptLong::REQUIRED_ARGUMENT参数缺失时自动报错?
解决方案
GetoptLong本身仅会校验已传入参数的格式合法性(比如必填参数是否附带了对应值),不会主动校验标记为REQUIRED_ARGUMENT的参数是否被传入。要实现必填参数缺失时的报错,需要手动添加校验逻辑,以下是几种可行方案:
方案一:遍历解析后检查必填项
将选项配置单独存储,遍历解析参数时记录已传入的选项,之后对比所有必填选项,检查是否存在缺失:
require "getoptlong" # 定义所有选项配置 options_config = [ [ "--argument", "-a", GetoptLong::REQUIRED_ARGUMENT ], [ "--other", "-o", GetoptLong::REQUIRED_ARGUMENT ], [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ] ] parser = GetoptLong.new(*options_config) passed_options = [] # 遍历解析参数,同时记录已传入的选项 parser.each do |opt, arg| passed_options << opt # 这里添加参数处理逻辑,比如赋值给变量 end # 提取所有必填选项的长名称 required_options = options_config.select { |conf| conf[2] == GetoptLong::REQUIRED_ARGUMENT }.map { |conf| conf[0] } # 检查并抛出缺失错误 missing = required_options - passed_options unless missing.empty? raise GetoptLong::MissingArgument, "Missing required option(s): #{missing.join(', ')}" end
方案二:结合错误处理与手动校验
先调用.each触发格式校验(比如必填参数是否带值),之后再手动检查所有必填参数是否都被传入,统一处理错误:
require "getoptlong" parser = GetoptLong.new( [ "--argument", "-a", GetoptLong::REQUIRED_ARGUMENT ], [ "--another", "-b", GetoptLong::REQUIRED_ARGUMENT ] ) required_args_received = [] begin parser.each do |opt, arg| required_args_received << opt if %w[--argument --another].include?(opt) # 处理参数逻辑 end # 校验必填参数是否全部传入 if required_args_received.size < 2 raise GetoptLong::MissingArgument, "Required options --argument and --another must be provided" end rescue GetoptLong::Error => e puts "Error: #{e.message}" exit 1 end
方案三:封装校验逻辑复用
把必填项校验逻辑封装成独立方法,方便在多个脚本中复用:
require "getoptlong" # 校验必填选项的方法 def validate_required_options(options_config, passed_options) required_options = options_config.select { |conf| conf[2] == GetoptLong::REQUIRED_ARGUMENT }.map(&:first) missing_options = required_options - passed_options unless missing_options.empty? raise GetoptLong::MissingArgument, "Missing required options: #{missing_options.join(', ')}" end end # 使用示例 options_config = [ [ "--name", "-n", GetoptLong::REQUIRED_ARGUMENT ], [ "--age", "-g", GetoptLong::REQUIRED_ARGUMENT ], [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ] ] parser = GetoptLong.new(*options_config) passed_options = [] parser.each do |opt, arg| passed_options << opt # 处理参数逻辑 end # 执行校验 validate_required_options(options_config, passed_options)
内容的提问来源于stack exchange,提问作者fguillen
相关产品推荐
相关产品推荐

