16

OptionParser では、オプションを必須にすることができますが、その値を省略すると、後続のオプションの名前が値として使用され、残りのコマンド ライン解析が台無しになります。オプションの値をエコーするテスト ケースを次に示します。

$ ./test_case.rb --input foo --output bar
output  bar
input  foo

最初のオプションの値を省略します。

$ ./test_case.rb --input  --output bar
input  --output

別のオプション名を値として取るのを防ぐ方法はありますか? ありがとう!

テストケースコードは次のとおりです。

#!/usr/bin/env ruby
require 'optparse'
files = Hash.new

option_parser = OptionParser.new do |opts|
  opts.on('-i', '--input FILENAME', 'Input filename - required') do |filename|
    files[:input] = filename
  end
  opts.on('-o', '--output FILENAME', 'Output filename - required') do |filename|
    files[:output] = filename
  end
end

begin
  option_parser.parse!(ARGV)
rescue OptionParser::ParseError
  $stderr.print "Error: " + $! + "\n"
  exit
end

files.keys.each do |key|
  print "#{key}  #{files[key]}\n"
end
4

4 に答える 4

8

あなたがしたいことは良い考えではありません。「--output」という名前のファイルが本当にある場合はどうなりますか? これは、Unix では完全に有効なファイル名です。すべての Unix プログラムのオプション解析は、Ruby のものと同じように機能するため、変更しないでください。変更すると、プログラムが他のすべてのものとは勝手に異なってしまい、混乱を招き、「最小の驚きの原則」に違反するからです。

本当の問題は、そもそもなぜこの問題を抱えているのかということです。おそらく、別のプログラムからプログラムを実行していて、親プログラムが --input へのパラメーターとして空のファイル名を提供しているため、 --input へのパラメーターとして --output が表示されます。コマンドラインで渡すファイル名を常に引用符で囲むことで、これを回避できます。

./test_case.rb --input "" --output "bar"

次に --input は空白になり、それは簡単に検出できます。

また、 --input が --output に設定されている場合 (および --output が実際のファイルではない場合)、 --input ファイルを開こうとするだけでよいことに注意してください。失敗した場合は、次のようなメッセージを出力します。

can't open input file: --output: file not found

そして、それはユーザーが何を間違えたのかを明確にする必要があります。

于 2010-03-31T15:47:19.500 に答える
2

これを試して:

opts.on('-i', '--input FILENAME', 'Input filename - required') do |filename|
  files[:input] = filename
end

opts.on('-o', '--output FILENAME', 'Output filename - required') do |filename|
  files[:output] = filename
end

opts.on("-h", "--help", "Show this message") do 
  puts opts
  exit
end


begin
  ARGV << "-h" if ARGV.size != 2   
  option_parser.parse!(ARGV)
rescue OptionParser::ParseError
  $stderr.print "Error: " + $! + "\n"
  exit
end
于 2012-02-01T11:27:56.027 に答える
1

この場合、必須--outputオプションが欠落しているため、 を呼び出した後にこれを行いますparse!

unless files[:input] && files[:output]
  $stderr.puts "Error: you must specify both --input and --output options."
  exit 1
end
于 2010-03-30T20:00:09.040 に答える
0

OK - これは機能します - on() 呼び出しの正規表現は、「-」で始まらない限り、任意の文字列を許可します

--input に引数を渡さず、下流に別のオプションがある場合、そのオプション キーが --input の引数として使用されます。(例: --input --output)。正規表現はそれをキャッチし、エラー メッセージを確認します。レポートされる引数が「-」で始まる場合、正しいエラー メッセージを出力します。つまり、引数が不足しているということです。きれいではありませんが、うまくいくようです。

ここに私の作業テストケースがあります:

#!/usr/bin/env ruby
require 'optparse'
files = Hash.new

option_parser = OptionParser.new do |opts|
  opts.on('-i FILENAME', '--input FILENAME', /\A[^\-]+/, 'Input filename - required') do |filename|
    files[:input] = filename
  end
  opts.on('-o FILENAME', '--output FILENAME', /\A[^\-]+/, 'Output filename - required') do |filename|
    files[:output] = filename
  end
end

begin
  option_parser.parse!(ARGV)
rescue OptionParser::ParseError
  if $!.to_s =~ /invalid\s+argument\:\s+(\-\-\S+)\s+\-/
    $stderr.print "Error: missing argument: #{$1}\n"
  else 
    $stderr.print "Error: " + $! + "\n"
  end  
  exit
end

files.keys.each do |key|
  print "#{key}  #{files[key]}\n"
end
于 2010-03-30T21:11:15.767 に答える