2010-03-30 33 views
17

Trong OptionParser tôi có thể thực hiện một tùy chọn bắt buộc, nhưng nếu tôi bỏ qua giá trị đó, nó sẽ lấy tên của bất kỳ tùy chọn nào sau đây làm giá trị, vặn phần còn lại của phân tích cú pháp dòng lệnh. Đây là một trường hợp thử nghiệm âm vang các giá trị của các tùy chọn:Làm cách nào để xử lý một đối số bắt buộc bị thiếu trong Ruby OptionParser?

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

Bây giờ bỏ qua các giá trị cho các tùy chọn đầu tiên:

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

Có một số cách để ngăn chặn nó dùng một tên khác tùy chọn như một giá trị? Cảm ơn!

Đây là mã test:

#!/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 

Trả lời

2

Trong trường hợp này, --output tùy chọn bắt buộc là mất tích, do đó làm điều này sau khi gọi parse!:

unless files[:input] && files[:output] 
    $stderr.puts "Error: you must specify both --input and --output options." 
    exit 1 
end 
+0

Ừ ... mà giải quyết trường hợp thử nghiệm, nhưng tôi thực sự hy vọng tôi có thể làm điều này trong khối OptionParser.new nơi mà nó thuộc về. Bạn phải có khả năng bao gồm một/mẫu/trong một cuộc gọi on() mà bất kỳ đối số nào phải khớp - nhưng tôi chưa nhận được tính năng này. Cảm ơn! –

1

OK - công trình này - thường xuyên biểu thức trong cuộc gọi on() cho phép bất kỳ chuỗi nào miễn là nó không bắt đầu bằng '-'

Nếu tôi không chuyển đối số đến - đầu vào và thứ ere là một tùy chọn khác ở hạ lưu sau đó nó sẽ lấy khóa tùy chọn đó làm đối số cho --input. (ví dụ: - đầu vào - đầu ra). Regexp bắt được và sau đó tôi kiểm tra thông báo lỗi. Nếu đối số nó báo cáo bắt đầu bằng '-' tôi xuất ra thông báo lỗi chính xác, cụ thể là có một đối số còn thiếu. Không đẹp nhưng có vẻ như nó hoạt động.

Đây là trường hợp thử nghiệm làm việc của tôi:

#!/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 
9

gì bạn muốn làm không phải là một ý tưởng tốt. Điều gì xảy ra nếu bạn thực sự có một tệp có tên "--output"? Đây là một tên tập tin hoàn toàn hợp lệ trên Unix. Mỗi phân tích cú pháp tùy chọn của chương trình Unix hoạt động theo cách mà ruby ​​đang thực hiện, vì vậy bạn không nên thay đổi nó, bởi vì chương trình của bạn sẽ khác với các thứ khác, gây nhầm lẫn và vi phạm "nguyên tắc ít ngạc nhiên nhất".

Câu hỏi thực sự là: tại sao bạn gặp vấn đề này ngay từ đầu? Có lẽ bạn đang chạy chương trình của bạn từ một chương trình khác, và chương trình cha mẹ đang cung cấp một tên tệp trống làm tham số cho --input, làm cho nó thấy - đầu ra như tham số tới --input. Bạn có thể giải quyết vấn đề này bằng cách luôn trích dẫn tên tệp mà bạn truyền trên dòng lệnh:

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

Sau đó - đầu vào sẽ trống, và dễ phát hiện.

Cũng lưu ý rằng nếu - đầu vào được đặt thành - đầu ra (và - đầu ra không phải là tệp thực) bạn chỉ có thể thử mở tệp --input. Nếu không thành công, hãy in một thông báo như:

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

Và điều đó sẽ làm rõ với người dùng những gì họ đã làm sai.

+3

+1 không bao giờ cố khắc phục điều gì đó bằng cách ẩn nó bằng mã thông minh –

2

thử điều này:

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 
Các vấn đề liên quan