रूबी स्क्रिप्ट को कमांड लाइन के माध्यम से चर पास करें


275

मैंने विंडोज पर RubyInstaller स्थापित किया है और मैं IMAP सिंक चला रहा हूं, लेकिन मुझे सैकड़ों खातों को सिंक करने के लिए इसका उपयोग करने की आवश्यकता है। अगर मैं इन चर को कमांड लाइन के माध्यम से पास कर सकता हूं तो मैं पूरी प्रक्रिया को बेहतर तरीके से स्वचालित कर सकता हूं।

# Source server connection info.
SOURCE_NAME = 'username@example.com'
SOURCE_HOST = 'mail.example.com'
SOURCE_PORT = 143
SOURCE_SSL  = false
SOURCE_USER = 'username'
SOURCE_PASS = 'password'

# Destination server connection info.
DEST_NAME = 'username@gmail.com'
DEST_HOST = 'imap.gmail.com'
DEST_PORT = 993
DEST_SSL  = true
DEST_USER = 'username@gmail.com'
DEST_PASS = 'password'

1
आप इस लोकप्रिय प्रश्न को एक वास्तविक प्रश्न में संपादित करने पर विचार कर सकते हैं ।
not2qubit

जवाबों:


465

कुछ इस तरह:

ARGV.each do|a|
  puts "Argument: #{a}"
end

फिर

$ ./test.rb "test1 test2"

या

v1 = ARGV[0]
v2 = ARGV[1]
puts v1       #prints test1
puts v2       #prints test2

84
मैं स्पष्ट रूप से कहना चाहूंगा कि ARGV [0] प्रोग्राम के नाम की ओर इशारा नहीं करता है, जैसा कि कुछ अन्य भाषाएं करती हैं। कार्यक्रम का नाम पाने के लिए, stackoverflow.com/questions/4834821/…
Sander Mertens

3
क्या `` test1 test2 '' केवल एक तर्क नहीं है?
वूलिवोंग

आपको इसे इस तरह चलाने में सक्षम होने के लिए फ़ाइल के #!/usr/bin/env rubyशीर्ष पर जोड़ना .rbहोगा:./test.rb
xamenrax

191

पहिया को मजबूत न करें; रूबी की कूल-कूल ऑप्शनपर्सर लाइब्रेरी देखें।

यह झंडे / स्विच, वैकल्पिक या आवश्यक मान वाले मापदंडों की पार्सिंग प्रदान करता है, एक विकल्प में मापदंडों की सूचियों को पार्स कर सकता है और आपके लिए आपकी सहायता उत्पन्न कर सकता है।

इसके अलावा, यदि आपकी किसी भी जानकारी को पारित किया जा रहा है, तो वह बहुत स्थिर है, जो रनों के बीच नहीं बदलती है, इसे एक YAML फ़ाइल में डालें जो पार्स हो जाती है। इस तरह आपके पास कमांड-लाइन पर हर बार बदलने वाली चीजें हो सकती हैं, और आपके कोड के बाहर कभी-कभी कॉन्फ़िगर की जाने वाली चीजें। रखरखाव के लिए डेटा और कोड का अलग होना अच्छा है।

यहाँ कुछ नमूने के साथ खेलने के लिए कर रहे हैं:

require 'optparse'
require 'yaml'

options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on('-n', '--sourcename NAME', 'Source name') { |v| options[:source_name] = v }
  opts.on('-h', '--sourcehost HOST', 'Source host') { |v| options[:source_host] = v }
  opts.on('-p', '--sourceport PORT', 'Source port') { |v| options[:source_port] = v }

end.parse!

dest_options = YAML.load_file('destination_config.yaml')
puts dest_options['dest_name']

यह एक नमूना YAML फ़ाइल है यदि आपके गंतव्य बहुत स्थिर हैं:

--- 
dest_name: username@gmail.com
dest_host: imap.gmail.com
dest_port: 993
dest_ssl: true
dest_user: username@gmail.com
dest_pass: password

यह आपको आसानी से एक YAML फ़ाइल उत्पन्न करने देगा:

require 'yaml'

yaml = {
  'dest_name' => 'username@gmail.com',
  'dest_host' => 'imap.gmail.com',
  'dest_port' => 993,
  'dest_ssl'  => true,
  'dest_user' => 'username@gmail.com',
  'dest_pass' => 'password'
}

puts YAML.dump(yaml)

2
ऑप्टपर्स लिंक मृत है। रूबी-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/…
केसी

7
उत्कृष्ट जवाब; जोड़ने के लायक हो सकता है कि ऑप्शन-पार्सिंग के बाद, ARGVकेवल ऑपरेंड शामिल हैं, यदि कोई हो (जो कि, शेष, गैर-विकल्प तर्क हैं)।
22

27

दुर्भाग्य से, रूबी इस तरह के गुजर तंत्र का समर्थन नहीं करता है जैसे कि AWK:

> awk -v a=1 'BEGIN {print a}'
> 1

इसका मतलब है कि आप अपनी स्क्रिप्ट में नामित मानों को सीधे पास नहीं कर सकते।

Cmd विकल्पों का उपयोग करने में मदद मिल सकती है:

> ruby script.rb val_0 val_1 val_2

# script.rb
puts ARGV[0] # => val_0
puts ARGV[1] # => val_1
puts ARGV[2] # => val_2

रूबी ARGVसरणी में सभी cmd तर्कों को संग्रहीत करता है, स्क्रिप्टनाम स्वयं $PROGRAM_NAMEचर का उपयोग करके कैप्चर किया जा सकता है ।

स्पष्ट नुकसान यह है कि आप मूल्यों के क्रम पर निर्भर करते हैं।

यदि आपको केवल बुलियन स्विच की जरूरत -sहै तो रूबी दुभाषिया के विकल्प का उपयोग करें :

> ruby -s -e 'puts "So do I!" if $agreed' -- -agreed
> So do I!

कृपया --स्विच पर ध्यान दें , अन्यथा रूबी एक विकल्प के बारे में शिकायत करेगी -agreed, इसलिए इसे अपने cmd इनवोकेशन के स्विच के रूप में पास करें। आपको निम्नलिखित मामले में इसकी आवश्यकता नहीं है:

> ruby -s script_with_switches.rb -agreed
> So do I!

नुकसान यह है कि आप वैश्विक चर के साथ गड़बड़ करते हैं और केवल तार्किक सच / गलत मान रखते हैं।

आप पर्यावरण चर से मूल्यों का उपयोग कर सकते हैं:

> FIRST_NAME='Andy Warhol' ruby -e 'puts ENV["FIRST_NAME"]'
> Andy Warhol

कमियां यहां मौजूद हैं, आपको स्क्रिप्ट इनवोकेशन (केवल अपनी रूबी प्रक्रिया के लिए) से पहले या उन्हें निर्यात करने के लिए सभी चर सेट करने होंगे (बीएएस जैसे गोले):

> export FIRST_NAME='Andy Warhol'
> ruby -e 'puts ENV["FIRST_NAME"]'

बाद के मामले में, आपका डेटा एक ही शेल सत्र में सभी के लिए और सभी उपप्रकारों के लिए पठनीय होगा, जो एक गंभीर सुरक्षा निहितार्थ हो सकता है।

और कम से कम आप getoptlong और Optparse का उपयोग करके एक विकल्प पार्सर को लागू कर सकते हैं ।

हैप्पी हैकिंग!


1

आप भी आजमा सकते हैं cliqr। यह बहुत नया और सक्रिय विकास में है। लेकिन उपयोग के लिए तैयार स्थिर रिलीज हैं। ये है git repo: https://github.com/anshulverma/cliqr

यह कैसे उपयोग किया जा सकता है पर एक विचार प्राप्त करने के लिए उदाहरण फ़ोल्डर में देखें।


0

इस कोड को कमांड लाइन पर चलाएं और N का मान दर्ज करें:

N  = gets; 1.step(N.to_i, 1) { |i| print "hello world\n" }

0

जब तक यह सबसे तुच्छ मामला नहीं है, रूबी में कमांड लाइन विकल्पों का उपयोग करने का केवल एक ही तरीका है। इसे यहां डॉकटॉप और डॉक्यूमेंट कहा जाता है

इसके साथ क्या अद्भुत है, क्या यह सरलता है। आपको बस इतना करना है, अपने आदेश के लिए "सहायता" पाठ निर्दिष्ट करें। वहां आप जो भी लिखेंगे, वह स्टैंडअलोन (!) माणिक लाइब्रेरी द्वारा ऑटो-पार्स किया जाएगा ।

से उदाहरण :

#!/usr/bin/env ruby
require 'docopt.rb'

doc = <<DOCOPT
Usage: #{__FILE__} --help
       #{__FILE__} -v...
       #{__FILE__} go [go]
       #{__FILE__} (--path=<path>)...
       #{__FILE__} <file> <file>

Try: #{__FILE__} -vvvvvvvvvv
     #{__FILE__} go go
     #{__FILE__} --path ./here --path ./there
     #{__FILE__} this.txt that.txt

DOCOPT

begin
  require "pp"
  pp Docopt::docopt(doc)
rescue Docopt::Exit => e
  puts e.message
end

उत्पादन:

$ ./counted_example.rb -h
Usage: ./counted_example.rb --help
       ./counted_example.rb -v...
       ./counted_example.rb go [go]
       ./counted_example.rb (--path=<path>)...
       ./counted_example.rb <file> <file>

Try: ./counted_example.rb -vvvvvvvvvv
     ./counted_example.rb go go
     ./counted_example.rb --path ./here --path ./there
     ./counted_example.rb this.txt that.txt

$ ./counted_example.rb something else
{"--help"=>false,
 "-v"=>0,
 "go"=>0,
 "--path"=>[],
 "<file>"=>["something", "else"]}

$ ./counted_example.rb -v
{"--help"=>false, "-v"=>1, "go"=>0, "--path"=>[], "<file>"=>[]}

$ ./counted_example.rb go go
{"--help"=>false, "-v"=>0, "go"=>2, "--path"=>[], "<file>"=>[]}

का आनंद लें!


0

आपको कंसोल_रनर मणि की कोशिश करनी चाहिए । यह रत्न आपके शुद्ध रूबी कोड को कमांड-लाइन से निष्पादन योग्य बनाता है। आपको बस अपने कोड में YARD एनोटेशन जोड़ना होगा :

# @runnable This tool can talk to you. Run it when you are lonely.
#   Written in Ruby.  
class MyClass

    def initialize
      @hello_msg = 'Hello' 
      @bye_msg = 'Good Bye' 
    end

    # @runnable Say 'Hello' to you.
    # @param [String] name Your name
    # @param [Hash] options options
    # @option options [Boolean] :second_meet Have you met before?
    # @option options [String] :prefix Your custom prefix
    def say_hello(name, options = {})
      second_meet = nil
      second_meet = 'Nice to see you again!' if options['second_meet']
      prefix = options['prefix']
      message = @hello_msg + ', '
      message += "#{prefix} " if prefix
      message += "#{name}. "
      message += second_meet if second_meet
      puts message
    end

end

फिर इसे कंसोल से चलाएं:

$ c_run /projects/example/my_class.rb  say_hello -n John --second-meet --prefix Mr. 
-> Hello, Mr. John. Nice to see you again!

0

tl; डॉ

मुझे पता है कि यह पुराना है, लेकिन गेटटॉपलॉन्ग का यहां उल्लेख नहीं किया गया था और यह शायद आज कमांड लाइन के तर्कों को पार्स करने का सबसे अच्छा तरीका है।


पार्सिंग कमांड लाइन तर्क

मैं दृढ़ता से getoptlong की सलाह देता हूं । यह उपयोग करने के लिए बहुत आसान है और एक आकर्षण की तरह काम करता है। यहाँ ऊपर दिए गए लिंक से एक उदाहरण निकाला गया है

require 'getoptlong'

opts = GetoptLong.new(
    [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
    [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
)

dir = nil
name = nil
repetitions = 1
opts.each do |opt, arg|
    case opt
        when '--help'
            puts <<-EOF
hello [OPTION] ... DIR

-h, --help:
     show help

--repeat x, -n x:
     repeat x times

--name [name]:
     greet user by name, if name not supplied default is John

DIR: The directory in which to issue the greeting.
            EOF
        when '--repeat'
            repetitions = arg.to_i
        when '--name'
            if arg == ''
                name = 'John'
            else
                name = arg
            end
    end
end

if ARGV.length != 1
    puts "Missing dir argument (try --help)"
    exit 0
end

dir = ARGV.shift

Dir.chdir(dir)
for i in (1..repetitions)
    print "Hello"
    if name
        print ", #{name}"
    end
    puts
end

आप इसे इस तरह कह सकते हैं ruby hello.rb -n 6 --name -- /tmp

ओपी क्या करने की कोशिश कर रहा है

इस मामले में मुझे लगता है कि इस उत्तर में सुझाए गए अनुसार YAML फ़ाइलों का उपयोग करना सबसे अच्छा विकल्प है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.