在Ruby脚本中解析命令行参数 [英] Parse command line arguments in a Ruby script
问题描述
我想从命令行调用Ruby脚本,并传递键/值对的参数。
I want to call a Ruby script from the command line, and pass in parameters that are key/value pairs.
命令行调用:
$ ruby my_script.rb --first_name=donald --last_name=knuth
my_script.rb:
my_script.rb:
puts args.first_name + args.last_name
Ruby的标准方法是什么?在其他语言中,我通常必须使用选项解析器。在Ruby中,我看到我们有 ARGF.read
,但这似乎不适用于本例中的键/值对。
What is the standard Ruby way to do this? In other languages I usually have to use an option parser. In Ruby I saw we have ARGF.read
, but that does not seem to work key/value pairs like in this example.
OptionParser 看起来很有希望,但我无法确定它是否真的支持这种情况。
OptionParser looks promising, but I can't tell if it actually supports this case.
推荐答案
基于@MartinCortez的回答这是一个简短的一次性操作,可散列键/值对,其中值必须以 =
符号连接。它还支持不带值的标志参数:
Based on the answer by @MartinCortez here's a short one-off that makes a hash of key/value pairs, where the values must be joined with an =
sign. It also supports flag arguments without values:
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}
,因此您可以执行以下操作:
Called with -x=foo -h --jim=jam
it returns {"x"=>"foo", "h"=>nil, "jim"=>"jam"}
so you can do things like:
puts args['jim'] if args.key?('h')
#=> jam
尽管有多个库可以处理此问题,包括Ruby随附的 GetoptLong
-我个人更喜欢自己动手。这是我使用的模式,该模式使其具有合理的通用性,不依赖于特定的使用格式,并且足够灵活以允许以各种顺序混合使用标志,选项和必需的参数:
While there are multiple libraries to handle this—including GetoptLong
included with Ruby—I personally prefer to roll my own. Here's the pattern I use, which makes it reasonably generic, not tied to a specific usage format, and flexible enough to allow intermixed flags, options, and required arguments in various orders:
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脚本中解析命令行参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!