代码之家  ›  专栏  ›  技术社区  ›  Robin Rodricks

通过命令行将变量传递给Ruby脚本

  •  256
  • Robin Rodricks  · 技术社区  · 14 年前

    我已经在Windows上安装了RubyInstaller并且正在运行 IMAP Sync 但我需要用它来同步数百个帐户。如果我可以通过命令行将这些变量传递给它,我可以更好地自动化整个过程。

    # 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'
    
    7 回复  |  直到 11 年前
        1
  •  450
  •   NowNick ceth    8 年前

    像这样的:

    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
    
        2
  •  188
  •   the Tin Man    11 年前

    别再发明轮子了,看看鲁比的酷劲 OptionParser 图书馆。

    它提供了标志/开关的解析,具有可选或必需值的参数,可以将参数列表解析为单个选项,并可以为您生成帮助。

    另外,如果传入的任何信息都是静态的,在运行之间不会发生变化,请将其放入一个经过解析的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)
    
        3
  •  26
  •   Andrei Beliankou    11 年前

    不幸的是,Ruby不支持这样的传递机制,例如AWK:

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

    这意味着您不能将命名值直接传递到脚本中。

    使用命令选项可能会有帮助:

    > 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在 ARGV 数组,可以使用 $PROGRAM_NAME 变量。

    明显的缺点是依赖于值的顺序。

    如果只需要布尔开关,请使用 -s 关于Ruby解释器:

    > 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
    

    这里的缺点是,必须在脚本调用之前设置所有变量(仅适用于您的ruby进程)或导出它们(BASH之类的shell):

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

    在后一种情况下,您的数据对同一shell会话中的每个人和所有子进程都是可读的,这可能会严重影响安全性。

    至少可以使用 getoptlong optparse .

    快乐黑客!

        4
  •  1
  •   nuaavee    10 年前

    你也可以试试 cliqr . 它很新,而且正在积极发展中。但也有稳定的版本可以使用。这是git回购协议: https://github.com/anshulverma/cliqr

    查看示例文件夹,了解如何使用它。

        5
  •  1
  •   the Tin Man    9 年前

    在命令行上运行此代码并输入N的值:

    N  = gets; 1.step(N.to_i, 1) { |i| print "hello world\n" }
    
        6
  •  1
  •   not2qubit    7 年前

    除非这是最简单的情况,否则在Ruby中只有一种明智的方法可以使用命令行选项。它被称为 docopt 并记录在案 here .

    令人惊奇的是,它很简单。 您只需指定命令的“帮助”文本。 你在那里写的东西会被 独立的 (!) 鲁比图书馆。

    example :

    #!/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>"=>[]}
    

    享受吧!

        7
  •  0
  •   Yuri Karpovich    6 年前

    你应该试试 console_runner 宝石。这个gem使您的纯Ruby代码可以从命令行执行。你只需要加上 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!