Değişkenleri komut satırıyla Ruby komut dosyasına geçirme


275

RubyInstaller'ı Windows'a yükledim ve IMAP Sync çalıştırıyorum, ancak yüzlerce hesabı senkronize etmek için kullanmam gerekiyor. Bu değişkenleri komut satırından geçirebilseydim tüm süreci daha iyi otomatikleştirebilirdim.

# 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
Bu popüler soruyu gerçek bir soru olarak düzenlemeyi düşünebilirsiniz .
not2qubit

Yanıtlar:


465

Bunun gibi bir şey:

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

sonra

$ ./test.rb "test1 test2"

veya

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

84
Açıkça belirtmek isterim ki ARGV [0] diğer diller gibi program ismini göstermiyor. Program adını almak için bkz. Stackoverflow.com/questions/4834821/…
Sander Mertens

3
"Test1 test2" sadece tek bir argüman değil midir?
wuliwong

Bu şekilde çalıştırabilmek için dosyanın #!/usr/bin/env rubyüstüne eklemeniz gerekir .rb:./test.rb
xamenrax

191

Tekerleği yeniden icat etmeyin; Ruby'nin yol serin OptionParser kütüphanesine göz atın .

Bayrakların / anahtarların, isteğe bağlı veya gerekli değerlere sahip parametrelerin ayrıştırılmasını sağlar, parametre listelerini tek bir seçenekte ayrıştırabilir ve sizin için yardımınızı oluşturabilir.

Ayrıca, iletilen bilgilerinizden herhangi biri oldukça statikse, bu işlemler arasında değişmezse, ayrıştırılan bir YAML dosyasına koyun. Bu şekilde, komut satırında her seferinde değişen ve kodunuzun dışında zaman zaman yapılandırılan değişikliklere sahip olabilirsiniz. Veri ve kod ayrımı bakım için iyidir.

İşte oynamak için bazı örnekler:

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']

Hedefleriniz oldukça statikse bu örnek bir YAML dosyasıdır:

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

Bu, kolayca bir YAML dosyası oluşturmanıza izin verir:

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
OptParse bağlantısı öldü. Deneyin ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/…
Casey

7
Mükemmel cevap; seçenek ayrıştırma işlemi tamamlandıktan sonra ARGV, yalnızca varsa işlenenleri (diğer bir deyişle kalan NON-seçenek bağımsız değişkenlerini) içerdiğini eklemeye değebilir.
mklement0

27

Ne yazık ki Ruby, örneğin AWK gibi bir geçiş mekanizmasını desteklemez:

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

Bu, adlandırılmış değerleri doğrudan komut dosyanıza geçiremeyeceğiniz anlamına gelir.

Cmd seçeneklerini kullanmak yardımcı olabilir:

> 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

Ruby tüm cmd argümanlarını ARGVdizide saklar , scriptname $PROGRAM_NAMEdeğişkenini kullanarak yakalanabilir .

Bariz dezavantaj, değerlerin sırasına bağlı olmanızdır.

Yalnızca Boole anahtarlarına ihtiyacınız varsa -sRuby yorumlayıcı seçeneğini kullanın :

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

Lütfen --anahtarı not edin , aksi takdirde Ruby varolmayan bir seçenek hakkında şikayet edecektir -agreed, bu yüzden cmd çağrınıza bir geçiş olarak geçirin. Aşağıdaki durumda buna ihtiyacınız yoktur:

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

Dezavantajı, global değişkenlerle uğraşmanız ve sadece mantıksal doğru / yanlış değerleriniz olmasıdır.

Ortam değişkenlerinden değerlere erişebilirsiniz:

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

Burada dezavantajlar var, tüm değişkenleri komut dosyası çağrısından önce ayarlamanız (sadece yakut işleminiz için) veya onları dışa aktarmanız (BASH gibi kabuklar):

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

İkinci durumda, verileriniz aynı kabuk oturumundaki herkes ve tüm alt işlemler için okunabilir, bu da ciddi bir güvenlik sonucu olabilir.

Ve en azından getoptlong ve optparse kullanarak bir seçenek ayrıştırıcısı uygulayabilirsiniz .

Mutlu hack!


1

Ayrıca deneyebilirsiniz cliqr. Oldukça yeni ve aktif gelişimde. Ancak kullanıma hazır kararlı sürümler vardır. İşte git repo: https://github.com/anshulverma/cliqr

Nasıl kullanılabileceği hakkında bir fikir edinmek için örnek klasöre bakın.


0

Bu kodu komut satırında çalıştırın ve N değerini girin:

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

0

En önemsiz durum olmadığı sürece, Ruby'de komut satırı seçeneklerini kullanmanın sadece bir aklı başında yolu vardır. Buna docopt denir ve burada belgelenir .

Onunla şaşırtıcı olan şey, basitlik. Tek yapmanız gereken, komutunuz için "yardım" metnini belirtmektir. Orada yazdıklarınız bağımsız (!) Ruby kütüphanesi tarafından otomatik olarak ayrıştırılır .

Gönderen Örneğin :

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

Çıktı:

$ ./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>"=>[]}

Zevk almak!


0

Console_runner gem'i denemelisiniz . Bu taş saf Ruby kodunuzu komut satırından yürütülebilir hale getirir. Tek ihtiyacınız olan kodunuza YARD ek açıklamaları eklemektir :

# @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

Sonra konsoldan çalıştırın:

$ 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; Dr.

Bunun eski olduğunu biliyorum, ama getoptlong burada bahsedilmedi ve muhtemelen bugün komut satırı argümanlarını ayrıştırmanın en iyi yolu.


Komut satırı bağımsız değişkenlerini ayrıştırma

Getoptlong şiddetle tavsiye ediyorum . Kullanımı oldukça kolaydır ve bir cazibe gibi çalışır. İşte yukarıdaki bağlantıdan bir örnek

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

Buna şöyle diyebilirsiniz ruby hello.rb -n 6 --name -- /tmp

OP ne yapmaya çalışıyor

Bu durumda en iyi seçeneğin YAML dosyalarını bu cevapta önerildiği gibi kullanmak olduğunu düşünüyorum

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.