我想从命令行调用Ruby脚本,并传入键/值对参数.

命令行调用:

$ ruby my_script.rb --first_name=donald --last_name=knuth

我的 playbook .rb:

puts args.first_name + args.last_name

Ruby的标准方法是什么?在其他语言中,我通常必须使用选项解析器.在Ruby中,我看到我们有ARGF.read个,但这似乎不适用于本例中的键/值对.

OptionParser看起来很有希望,但我不知道它是否真的支持这个案子.

推荐答案

根据@MartinCortez的回答,这里有一个简短的一次性方法,它会对键/值对进行散列,其中值必须用=号连接.它还支持不带值的标志参数:

args = Hash[ ARGV.join(' ').scan(/--?([^=\s]+)(?:=(\S+))?/) ]

或者…

args = Hash[ ARGV.flat_map{|s| s.scan(/--?([^=\s]+)(?:=(\S+))?/) } ]

调用-x=foo -h --jim=jam时,它返回{"x"=>"foo", "h"=>nil, "jim"=>"jam"},因此您可以执行以下操作:

puts args['jim'] if args.key?('h')
#=> jam

虽然有多个库可以处理这个问题,包括GetoptLong included with Ruby个库,但我个人更喜欢自己的库.以下是我使用的模式,它使其具有合理的通用性,不依赖于特定的使用格式,并且足够灵活,允许以各种顺序混合使用标志、选项和必需的参数:

USAGE = <<ENDUSAGE
Usage:
   docubot [-h] [-v] [create [-s shell] [-f]] directory [-w writer] [-o output_file] [-n] [-l log_file]
ENDUSAGE

HELP = <<ENDHELP
   -h, --help       Show this help.
   -v, --version    Show the version number (#{DocuBot::VERSION}).
   create           Create a starter directory filled with example files;
                    also copies the template for easy modification, if desired.
   -s, --shell      The shell to copy from.
                    Available shells: #{DocuBot::SHELLS.join(', ')}
   -f, --force      Force create over an existing directory,
                    deleting any existing files.
   -w, --writer     The output type to create [Defaults to 'chm']
                    Available writers: #{DocuBot::Writer::INSTALLED_WRITERS.join(', ')}
   -o, --output     The file or folder (depending on the writer) to create.
                    [Default value depends on the writer chosen.]
   -n, --nopreview  Disable automatic preview of .chm.
   -l, --logfile    Specify the filename to log to.

ENDHELP

ARGS = { :shell=>'default', :writer=>'chm' } # Setting default values
UNFLAGGED_ARGS = [ :directory ]              # Bare arguments (no flag)
next_arg = UNFLAGGED_ARGS.first
ARGV.each do |arg|
  case arg
    when '-h','--help'      then ARGS[:help]      = true
    when 'create'           then ARGS[:create]    = true
    when '-f','--force'     then ARGS[:force]     = true
    when '-n','--nopreview' then ARGS[:nopreview] = true
    when '-v','--version'   then ARGS[:version]   = true
    when '-s','--shell'     then next_arg = :shell
    when '-w','--writer'    then next_arg = :writer
    when '-o','--output'    then next_arg = :output
    when '-l','--logfile'   then next_arg = :logfile
    else
      if next_arg
        ARGS[next_arg] = arg
        UNFLAGGED_ARGS.delete( next_arg )
      end
      next_arg = UNFLAGGED_ARGS.first
  end
end

puts "DocuBot v#{DocuBot::VERSION}" if ARGS[:version]

if ARGS[:help] or !ARGS[:directory]
  puts USAGE unless ARGS[:version]
  puts HELP if ARGS[:help]
  exit
end

if ARGS[:logfile]
  $stdout.reopen( ARGS[:logfile], "w" )
  $stdout.sync = true
  $stderr.reopen( $stdout )
end

# etc.

Ruby相关问答推荐

当 node 名称是/包含整数时,使用 Nokogiri 解析非 XML 文档

Rack并发 - rack.multithread、async.callback 或两者兼而有之?

如何在 Ruby 中生成一个包含 n 个唯一随机数的列表?

如何使用 Ruby 的 optparse 解析没有名称的参数

get.chomp() 与 STDIN.gets.chomp() 有什么区别?

Ruby:p *1..10中的星号是什么意思

有没有办法通过哈希初始化对象?

退出(exit)和中止(abort)有什么区别?

如何使用 if..else 块的结果分配变量?

进程的 pid、ppid、uid、euid、gid 和 egid 有什么区别?

RSpec:每次指定对具有不同参数的方法的多次调用

include_examples和it_behaves_like有什么区别?

如何验证 RSpec 中的退出和中止?

是否可以使用 Ruby 读取文件的修改日期?

if语句末尾带有then有什么区别?

使用 Ruby CSV 在导出的 CSV 中更改字段分隔符/分隔符

Ruby 删除目录

使用整数作为哈希键

等号 ('=') 放在方法定义中的方法名称之后有什么作用?

以小时为单位的时差