2010-03-30 10 views
17

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 

उत्तर

2

इस मामले में, अनिवार्य --output विकल्प याद आ रही है, तो parse! बुला के बाद ऐसा करते हैं:

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

हाँ ... कि परीक्षण का मामला हल करती है, लेकिन मैं वास्तव में आशा करती हूं कि मैं OptionParser.new ब्लॉक जहां से वह संबंधित के भीतर ऐसा कर सकते हैं। आप एक/pattern/को ऑन() कॉल में शामिल करने में सक्षम होना चाहिए, जो कि किसी भी तर्क से मेल खाना चाहिए - लेकिन मुझे अभी तक यह काम नहीं मिल रहा है। धन्यवाद! –

1

ठीक है - यह काम करता है - नियमित रूप से ऑन() कॉल में अभिव्यक्ति किसी भी स्ट्रिंग को तब तक अनुमति देती है जब तक यह '0'

से शुरू नहीं होती है यदि मैं --input और th के लिए कोई तर्क नहीं देता ere डाउनस्ट्रीम का एक और विकल्प है तो यह उस विकल्प कुंजी को --input के तर्क के रूप में ले जाएगा। (उदा। - इनपुट - आउटपुट)। Regexp उस पकड़ता है और फिर मैं त्रुटि संदेश की जांच करता हूं। यदि तर्क यह रिपोर्ट '-' से शुरू होता है तो मैं सही त्रुटि संदेश आउटपुट करता हूं, अर्थात् एक गुम तर्क है। सुंदर नहीं है लेकिन ऐसा लगता है।

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

क्या आप क्या करना चाहते एक अच्छा विचार नहीं है:

यहाँ मेरे कार्य परीक्षण का मामला है। क्या होगा यदि आपके पास वास्तव में "--output" नाम की एक फ़ाइल है? यह यूनिक्स पर एक पूरी तरह से वैध फ़ाइल नाम है। प्रत्येक यूनिक्स प्रोग्राम का विकल्प पार्सिंग जिस तरह से रूबी कर रहा है, वैसे ही काम करता है, इसलिए आपको इसे बदलना नहीं चाहिए, क्योंकि तब आपका प्रोग्राम अन्य सभी चीज़ों से मनमाने ढंग से अलग होगा, जो भ्रमित है और "कम से कम आश्चर्य के सिद्धांत" का उल्लंघन करता है।

असली सवाल यह है कि: आपको यह समस्या पहली जगह क्यों है? शायद आप अपने प्रोग्राम को किसी अन्य प्रोग्राम से चला रहे हैं, और मूल प्रोग्राम --input के पैरामीटर के रूप में एक खाली फ़ाइल नाम प्रदान कर रहा है, जो इसे - इनपुट को पैरामीटर के रूप में --output के रूप में देखता है। आप इस के आसपास हमेशा नामों और आपके द्वारा कमांड लाइन पर पारित उद्धृत करके काम कर सकते हैं:

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

फिर --input खाली हो जाएगा, और है कि पता लगाने के लिए आसान है।

यह भी ध्यान दें कि अगर - इनपुट को आउटपुट पर सेट किया गया है (और --output वास्तविक फ़ाइल नहीं है) तो आप केवल - इनपुट फ़ाइल खोलने का प्रयास कर सकते हैं। यदि यह विफल हो जाता है, तो

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

और इससे उपयोगकर्ता को यह स्पष्ट करना चाहिए कि उन्होंने क्या किया है।

+3

+1 कभी भी चालाक कोड से छिपकर कुछ ठीक करने का प्रयास न करें –

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 
संबंधित मुद्दे