2012-02-02 12 views
5

n00b प्रश्न चेतावनी! यहां समस्या है: मैं एक शेल स्क्रिप्ट बना रहा हूं जिसमें कम से कम 3 तर्क होते हैं: एक स्ट्रिंग, एक पंक्ति संख्या, और कम से कम एक फ़ाइल।ruby ​​- कमांड लाइन तर्कों की अलग-अलग संख्याओं को सही ढंग से कैसे पार्स करें

मैंने एक स्क्रिप्ट लिखी है जो वास्तव में 3 तर्क स्वीकार करेगी, लेकिन मुझे नहीं पता कि एकाधिक फ़ाइल नाम तर्कों को कैसे संभालना है।

#!/usr/bin/env ruby 

the_string = ARGV[0] 
line_number = ARGV[1] 
the_file = ARGV[2] 

def insert_script(str, line_n, file) 
    f = file 
    s = str 
    ln = line_n.to_i 

    if (File.file? f) 
    read_in(f,ln,s) 
    else 
    puts "false" 
    end 
end 

def read_in(f,ln,s) 
    lines = File.readlines(f) 
    lines[ln] = s + "\n" 
    return lines 
end 

# run it 
puts insert_script(the_string, line_number, the_file) 

अब मुझे पता है कि यह एक ब्लॉक है कि सभी तर्कों के माध्यम से पुनरावृति जाएगा लिखने के लिए आसान है::

यहाँ मेरी कोड के प्रासंगिक भागों (वापस फ़ाइल आदि में लेखन लंघन) है

ARGV.each do |a| 
    puts a 
end 

लेकिन मुझे केवल अंतिम फ़ाइल नाम पर ARGV [2] (पहली फ़ाइल नाम) से तर्कों के माध्यम से लूप की आवश्यकता है।

मुझे पता है कि कम से कम - ऐसा करने के लिए कम से कम एक आसान तरीका है, लेकिन मैं नहीं देख सकता कि यह इस समय क्या है!

किसी भी मामले में - अगर कोई मुझे ट्यूटोरियल या उदाहरण में इंगित कर सकता है तो मुझे खुशी होगी, मुझे यकीन है कि वहाँ बहुत सारे हैं - लेकिन मुझे उन्हें नहीं लगता है।

धन्यवाद

+0

हर किसी से महान जवाब! सबको धन्यवाद। आमतौर पर यह मामला नहीं है कि मैं समझता हूं या यहां कई उत्तरों का उपयोग कर सकता हूं - इसलिए या तो मैं समझदार हो रहा हूं या यह एक विशेष रूप से आसान सवाल था या आप लोग सिर्फ अच्छे व्याख्याकर्ता हैं ... या तीनों के कुछ कॉम्बो! चीयर्स, बी –

उत्तर

5

यदि आप उन तत्वों को निकालने के लिए ARGV सरणी को संशोधित करते हैं जिन्हें आप अब फ़ाइल नामों के रूप में उपयोग करने में रूचि नहीं रखते हैं, तो आप treat all remaining elements as filenames and iterate over their contents with ARGF कर सकते हैं।

एक कौर है कि, एक छोटा सा उदाहरण यह और अधिक आसानी से प्रदर्शन करेंगे:

argf.rb:

#!/usr/bin/ruby 

str = ARGV.shift 
line = ARGV.shift 

ARGF.each do |f| 
    puts f 
end 
$ ./argf.rb one two argf.rb argf.rb 
#!/usr/bin/ruby 

str = ARGV.shift 
line = ARGV.shift 

ARGF.each do |f| 
    puts f 
end 
#!/usr/bin/ruby 

str = ARGV.shift 
line = ARGV.shift 

ARGF.each do |f| 
    puts f 
end 
$ 

दोargf.rb फ़ाइल की प्रतियां सांत्वना क्योंकि मुद्रित कर रहे हैं मैंने कमांड लाइन पर फ़ाइल नाम argf.rb दो बार दिया। यह प्रत्येक उल्लेख के लिए एक बार खोला और फिर से शुरू किया गया था।

यदि आप फ़ाइलों को अपनी सामग्री को पढ़ने के बजाय फ़ाइलों पर काम करना चाहते हैं, तो आप बस ARGV सरणी को संशोधित कर सकते हैं और फिर शेष तत्वों का सीधे उपयोग कर सकते हैं।

+0

यह सही है - ठीक है जो मैं देख रहा था और आसानी से मेरे n00bie मस्तिष्क द्वारा पकड़ा गया था। बहुत धन्यवाद! –

2

OptionParser पर एक नजर डालें - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html। यह आपको तर्कों की संख्या निर्दिष्ट करने की अनुमति देता है, भले ही वे अनिवार्य या वैकल्पिक हों, मिसिंग आर्ग्यूमेंट या अमान्य विकल्प जैसी त्रुटियों को संभाल लें।

+0

धन्यवाद सर्गेई - मैं ऑप्शन पार्सर में आया था, लेकिन मुझे थोड़ा डरावना पाया ... शायद मुझे बेहद शक्तिशाली यकीन है, लेकिन मैं सही प्रकार के समाधान सरनोल्ड का सुझाव दे रहा था। –

6

क्या आप एक सहायक मणि का उपयोग करने पर विचार करेंगे? Trollop कमांड लाइन पार्सिंग के लिए बहुत अच्छा है क्योंकि यह स्वचालित रूप से आप संदेश, लंबी और छोटी कमांड लाइन स्विच, आदि

require 'trollop' 

opts = Trollop::options do 
    opt :string, "The string", :type => :string 
    opt :line, "line number", :type => :int 
    opt :file, "file(s)", :type => :strings 
end 

p opts 

जब मैंने इसे "commandline.rb" कहते हैं और इसे चलाने में मदद देता है:

$ ruby commandline.rb --string "foo bar" --line 3 --file foo.txt bar.txt 

{:string=>"foo bar", :line=>3, :file=>["foo.txt", "bar.txt"], :help=>false, :string_given=>true, :line_given=>true, :file_given=>true} 
+0

हमम ... मैं इसे देख लूंगा - धन्यवाद मार्क! –

2

यदि आप किसी अन्य लाइब्रेरी का उपयोग नहीं करना चाहते हैं या ARGV सरणी को बदलना चाहते हैं तो एक वैकल्पिक (और कुछ हद तक उलझन) चाल है।

तक
2.upto(ARGV.length-1) do |i| 
    puts ARGV[i] 
end 
+0

धन्यवाद Retief - मेरा एक दोस्त और मैं आज रात इस रणनीति के साथ आया, लेकिन सुरुचिपूर्ण नहीं ... (छद्म कोड में) के साथ और अधिक: '2 से लंबाई -1 करने के लिए ...' आदि यह अधिक संक्षिप्त है - तो चीयर्स। –

3

विहित रास्ता shift उपयोग करने के लिए है, इसलिए की तरह है:

the_string = ARGV.shift 
line_number = ARGV.shift 
ARGV.each do |file| 
    puts insert_script(the_string, line_number, the_file) 
end 
+0

धन्यवाद डेव, इसकी सराहना करें। –

संबंधित मुद्दे