私は、スクリプトを書いていると私は値で--host
スイッチを必要としたいのですが、--host
スイッチが指定されていない場合、私は失敗して解析するオプションが欲しいです。Ruby OptionParserでどのように必要なスイッチ(引数ではない)を指定しますか?
私はそれを行う方法を理解できないようです。ドキュメントは、スイッチ自体ではなく、引数の値を必須にする方法だけを指定しているようです。
私は、スクリプトを書いていると私は値で--host
スイッチを必要としたいのですが、--host
スイッチが指定されていない場合、私は失敗して解析するオプションが欲しいです。Ruby OptionParserでどのように必要なスイッチ(引数ではない)を指定しますか?
私はそれを行う方法を理解できないようです。ドキュメントは、スイッチ自体ではなく、引数の値を必須にする方法だけを指定しているようです。
同じ技術は、他のオプションの構文解析ライブラリのために動作しますが、私は、あなたがここにoptparseは使用していると仮定しています。
最も簡単な方法は、あなたの選択したオプションの解析ライブラリを使用してパラメータを解析し、ホストの値がnilの場合はOptionParser :: MissingArgument例外を上げることが考えられます。
次のコードは
#!/usr/bin/env ruby
require 'optparse'
options = {}
optparse = OptionParser.new do |opts|
opts.on('-h', '--host HOSTNAME', "Mandatory Host Name") do |f|
options[:host] = f
end
end
optparse.parse!
#Now raise an exception if we have not found a host option
raise OptionParser::MissingArgument if options[:host].nil?
puts "Host = #{options[:host]}"
"は、宿主= somehost"
で実行しながら、欠落-hなし
./program -h somehost
単純なディスプレイのコマンドラインでこの例を実行示しファイル名は、次の出力が生成さ
./program:15: missing argument: (OptionParser::MissingArgument)
そして行方不明のスイッチに優しい出力を提供optparseが使ってアプローチ
/usr/lib/ruby/1.8/optparse.rb:451:in `parse': missing argument: -h (OptionParser::MissingArgument)
from /usr/lib/ruby/1.8/optparse.rb:1288:in `parse_in_order'
from /usr/lib/ruby/1.8/optparse.rb:1247:in `catch'
from /usr/lib/ruby/1.8/optparse.rb:1247:in `parse_in_order'
from /usr/lib/ruby/1.8/optparse.rb:1241:in `order!'
from /usr/lib/ruby/1.8/optparse.rb:1332:in `permute!'
from /usr/lib/ruby/1.8/optparse.rb:1353:in `parse!'
from ./program:13
それはそれは、ライブラリのネイティブ機能ではありません臭い - それは非常にDRYではありません必要なスイッチがもう少しあれば。ありがとう。 –
潜在的な例外を発生させるのではなく、 'Kernel.abort'を呼び出すことによってゼロ以外の状態で終了する方が好きです。オプションの引数を取ります。この引数を使用して、中止の理由を指定できます。 –
合意済み。それはまったくDRYではなく、そうでないことを恥ずかしく思うべきです。私の最初のコマンドラインアプリでは必須のスイッチが必要でしたので、これは含まれていません。 –
を生成-h ./programのコマンドラインで実行している:
#!/usr/bin/env ruby
require 'optparse'
options = {}
optparse = OptionParser.new do |opts|
opts.on('-f', '--from SENDER', 'username of sender') do |sender|
options[:from] = sender
end
opts.on('-t', '--to RECIPIENTS', 'comma separated list of recipients') do |recipients|
options[:to] = recipients
end
options[:number_of_files] = 1
opts.on('-n', '--num_files NUMBER', Integer, "number of files to send (default #{options[:number_of_files]})") do |number_of_files|
options[:number_of_files] = number_of_files
end
opts.on('-h', '--help', 'Display this screen') do
puts opts
exit
end
end
begin
optparse.parse!
mandatory = [:from, :to] # Enforce the presence of
missing = mandatory.select{ |param| options[param].nil? } # the -t and -f switches
unless missing.empty? #
raise OptionParser::MissingArgument.new(missing.join(', ')) #
end #
rescue OptionParser::InvalidOption, OptionParser::MissingArgument #
puts $!.to_s # Friendly output when parsing fails
puts optparse #
exit #
end #
puts "Performing task with options: #{options.inspect}"
-t
または-f
がショーを切り替えずに実行を次の出力:
Missing options: from, to
Usage: test_script [options]
-f, --from SENDER username of sender
-t, --to RECIPIENTS comma separated list of recipients
-n, --num_files NUMBER number of files to send (default 1)
-h, --help
begin/rescue節は引数の欠落や無効なスイッチ値などの他の失敗時にフレンドリなフォーマットを可能にします。たとえば、-n
スイッチの文字列を渡すとよいでしょう。
はneilfwsのコメントに従って修正しました – volund
これは悪くはありませんが、まだそれほど乾燥していません。最後に多くの作業を行う必要があり、スイッチを2か所で指定する必要があります。下の私の修正をチェックしてください。これははるかに単純で、多くのDRYです。私のブログでも:http://picklepumpers.com/wordpress/?p=949 –
それは素晴らしい答えです、ありがとうvolund。 –
未知(google)の回答は良いですが、マイナーエラーがあります。
rescue OptionParser::InvalidArgument, OptionParser::MissingArgument
OptionParser::InvalidOption, OptionParser::MissingArgument
する必要がありそうでない場合は、optparse.parse!
はOptionParser::InvalidOption
のための標準エラー出力ではなく、カスタムメッセージをトリガします。
私はあなたがダウンロードしてRubyGemsのからインストールすることができます宝石にこれを回しました。ORG:
gem install pickled_optparse
そして、あなたはgithubの上で更新され、プロジェクトのソースコードをチェックアウトすることができます。
http://github.com/PicklePumpers/pickled_optparse
- これは本当に、本当に、私はそれを修正私を悩ませた
- 前の投稿情報をおよびは、超DRYを使用していました。そのようなオプションの配列内のどこにでも必要なシンボル:
だけの追加に必要なスイッチにするために不足しているスイッチをプリントアウトするには、これらのいずれかを追加するにはOptionParserブロックの終わりに続いてopts.on("-f", "--foo [Bar]", String, :required, "Some required option") do |option|
@options[:foo] = option
end
をし、使用手順:
if opts.missing_switches?
puts opts.missing_switches
puts opts
exit
end
そして最後に、それはすべてあなたがどこかのプロジェクトに、次の「optparse_required_switches.rb」ファイルを追加したり、コマンドラインの解析を行うときに、それを必要とする必要が働くようにします。
私は私のブログ上の例ではほとんどの記事を書いた: http://picklepumpers.com/wordpress/?p=949
そしてここでは、その使用方法の一例と修正のOptionParserファイルです:
required_switches_example.rb
#!/usr/bin/env ruby
require 'optparse'
require_relative 'optparse_required_switches'
# Configure options based on command line options
@options = {}
OptionParser.new do |opts|
opts.banner = "Usage: test [options] in_file[.srt] out_file[.srt]"
# Note that :required can be anywhere in the parameters
# Also note that OptionParser is bugged and will only check
# for required parameters on the last option, not my bug.
# required switch, required parameter
opts.on("-s Short", String, :required, "a required switch with just a short") do |operation|
@options[:operation] = operation
end
# required switch, optional parameter
opts.on(:required, "--long [Long]", String, "a required switch with just a long") do |operation|
@options[:operation] = operation
end
# required switch, required parameter
opts.on("-b", "--both ShortAndLong", String, "a required switch with short and long", :required) do |operation|
@options[:operation] = operation
end
# optional switch, optional parameter
opts.on("-o", "--optional [Whatever]", String, "an optional switch with short and long") do |operation|
@options[:operation] = operation
end
# Now we can see if there are any missing required
# switches so we can alert the user to what they
# missed and how to use the program properly.
if opts.missing_switches?
puts opts.missing_switches
puts opts
exit
end
end.parse!
optparse_required_switches.rb
# Add required switches to OptionParser
class OptionParser
# An array of messages describing the missing required switches
attr_reader :missing_switches
# Convenience method to test if we're missing any required switches
def missing_switches?
[email protected]_switches.nil?
end
def make_switch(opts, block = nil)
short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
ldesc, sdesc, desc, arg = [], [], []
default_style = Switch::NoArgument
default_pattern = nil
klass = nil
n, q, a = nil
# Check for required switches
required = opts.delete(:required)
opts.each do |o|
# argument class
next if search(:atype, o) do |pat, c|
klass = notwice(o, klass, 'type')
if not_style and not_style != Switch::NoArgument
not_pattern, not_conv = pat, c
else
default_pattern, conv = pat, c
end
end
# directly specified pattern(any object possible to match)
if (!(String === o || Symbol === o)) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
if pattern.respond_to?(:convert)
conv = pattern.method(:convert).to_proc
else
conv = SPLAT_PROC
end
next
end
# anything others
case o
when Proc, Method
block = notwice(o, block, 'block')
when Array, Hash
case pattern
when CompletingHash
when nil
pattern = CompletingHash.new
conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
else
raise ArgumentError, "argument pattern given twice"
end
o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
when Module
raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
style = notwice(ArgumentStyle[o], style, 'style')
when /^--no-([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
not_pattern, not_conv = search(:atype, o) unless not_style
not_style = (not_style || default_style).guess(arg = a) if a
default_style = Switch::NoArgument
default_pattern, conv = search(:atype, FalseClass) unless default_pattern
ldesc << "--no-#{q}"
long << 'no-' + (q = q.downcase)
nolong << q
when /^--\[no-\]([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
if a
default_style = default_style.guess(arg = a)
default_pattern, conv = search(:atype, o) unless default_pattern
end
ldesc << "--[no-]#{q}"
long << (o = q.downcase)
not_pattern, not_conv = search(:atype, FalseClass) unless not_style
not_style = Switch::NoArgument
nolong << 'no-' + o
when /^--([^\[\]=\s]*)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
default_style = default_style.guess(arg = a)
default_pattern, conv = search(:atype, o) unless default_pattern
end
ldesc << "--#{q}"
long << (o = q.downcase)
when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
q, a = $1, $2
o = notwice(Object, klass, 'type')
if a
default_style = default_style.guess(arg = a)
default_pattern, conv = search(:atype, o) unless default_pattern
end
sdesc << "-#{q}"
short << Regexp.new(q)
when /^-(.)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
default_style = default_style.guess(arg = a)
default_pattern, conv = search(:atype, o) unless default_pattern
end
sdesc << "-#{q}"
short << q
when /^=/
style = notwice(default_style.guess(arg = o), style, 'style')
default_pattern, conv = search(:atype, Object) unless default_pattern
else
desc.push(o)
end
end
default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
if !(short.empty? and long.empty?)
s = (style || default_style).new(pattern || default_pattern, conv, sdesc, ldesc, arg, desc, block)
elsif !block
if style or pattern
raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
end
s = desc
else
short << pattern
s = (style || default_style).new(pattern, conv, nil, nil, arg, desc, block)
end
# Make sure required switches are given
if required && !(default_argv.include?("-#{short[0]}") || default_argv.include?("--#{long[0]}"))
@missing_switches ||= [] # Should be placed in initialize if incorporated into Ruby proper
# This is more clear but ugly and long.
#missing = "-#{short[0]}" if !short.empty?
#missing = "#{missing} or " if !short.empty? && !long.empty?
#missing = "#{missing}--#{long[0]}" if !long.empty?
# This is less clear and uglier but shorter.
missing = "#{"-#{short[0]}" if !short.empty?}#{" or " if !short.empty? && !long.empty?}#{"--#{long[0]}" if !long.empty?}"
@missing_switches << "Missing switch: #{missing}"
end
return s, short, long,
(not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
nolong
end
end
ホストが必要な場合は、確かにそれはオプションではない、それは引数です。
これを念頭に置いて、問題を解決する方法を次に示します。 ARGV
アレイを調べてホストが指定されているかどうかを確認し、指定されていない場合はabort("You must specify a host!")
などと呼び出して、プログラムをエラー状態で終了させることができます。
あなたはこのような何か場合:
opts.on('-h', '--host',
'required host name [STRING]') do |h|
someoptions[:host] = h || nil
end
を使用すると、--host後--hostおよび/または値なしを指定しない場合、someoptions[:host]
は(コマンドラインからの値またはnil
のどちらかになります)、あなたは簡単にそれをテスト(条件付きで失敗する可能性があります)解析の後:
fail "Hostname not provided" unless someoptions[:host]
私はあなたの貢献をまとめ明確で簡潔な解決策を考え出しました。メッセージには、欠落した引数を含むOptionParser::MissingArgument
例外が発生します。この例外は、ブロックrescue
でキャッチされ、残りの例外はOptionParser
から発生します。いくつかのフィールドが欠落している場合には、その後parse!
、
./program
missing argument: host
Usage: program [options]
-h, --host hostname Host name
アイデアがOptionParser
を定義することであることを、そしてputs
:
#!/usr/bin/env ruby
require 'optparse'
options = {}
optparse = OptionParser.new do |opts|
opts.on('-h', '--host hostname', "Host name") do |host|
options[:host] = host
end
end
begin
optparse.parse!
mandatory = [:host]
missing = mandatory.select{ |param| options[param].nil? }
raise OptionParser::MissingArgument, missing.join(', ') unless missing.empty?
rescue OptionParser::ParseError => e
puts e
puts optparse
exit
end
この例を実行します。デフォルトでfilename
を空文字列に設定するのはおそらく最善の方法ではありませんが、あなたはその考えを持っています。
require 'optparse'
filename = ''
options = OptionParser.new do |opts|
opts.banner = "Usage: swift-code-style.rb [options]"
opts.on("-iNAME", "--input-filename=NAME", "Input filename") do |name|
filename = name
end
opts.on("-h", "--help", "Prints this help") do
puts opts
exit
end
end
options.parse!
if filename == ''
puts "Missing filename.\n---\n"
puts options
exit
end
puts "Processing '#{filename}'..."
-i filename
が欠落している場合は、それが表示されます。あなたは、より複雑な例を与える必要が
~/prj/gem/swift-code-kit ./swift-code-style.rb
Missing filename.
---
Usage: swift-code-style.rb [options]
-i, --input-filename=NAME Input filename
-h, --help Prints this help
を.... – khelll