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

Rob*_*cks 262 ruby command-line

我在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'
Run Code Online (Sandbox Code Playgroud)

dem*_*mas 450

像这样的东西:

ARGV.each do|a|
  puts "Argument: #{a}"
end
Run Code Online (Sandbox Code Playgroud)

然后

$ ./test.rb "test1 test2"
Run Code Online (Sandbox Code Playgroud)

要么

v1 = ARGV[0]
v2 = ARGV[1]
puts v1       #prints test1
puts v2       #prints test2
Run Code Online (Sandbox Code Playgroud)

  • 我想明确指出ARGV [0]并没有像其他语言那样指向程序名称.要获取程序名称,请参阅http://stackoverflow.com/questions/4834821/how-can-i-get-the-name-of-the-command-called-for-usage-prompts-in-ruby (83认同)
  • ““ test1 test2”不只是一个参数吗? (2认同)

the*_*Man 188

不要重新发明轮子; 看看Ruby的酷炫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']
Run Code Online (Sandbox Code Playgroud)

如果您的目标是非常静态的,那么这是一个示例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
Run Code Online (Sandbox Code Playgroud)

这将让您轻松生成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)
Run Code Online (Sandbox Code Playgroud)

  • 优秀答案; 可能值得补充一点,在选项解析完成后,`ARGV`只包含操作数,如果有的话(即剩余的NON选项参数). (7认同)
  • OptParse链接已经死了.试试http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html (2认同)

And*_*kou 26

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

> awk -v a=1 'BEGIN {print a}'
> 1
Run Code Online (Sandbox Code Playgroud)

这意味着您无法直接将命名值传递到脚本中.

使用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
Run Code Online (Sandbox Code Playgroud)

Ruby将所有cmd参数存储在ARGV数组中,可以使用$PROGRAM_NAME变量捕获scriptname本身.

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

如果只需要布尔开关,请使用-sRuby解释器的选项:

> ruby -s -e 'puts "So do I!" if $agreed' -- -agreed
> So do I!
Run Code Online (Sandbox Code Playgroud)

请注意--切换,否则Ruby会抱怨一个不存在的选项-agreed,所以将它作为一个开关传递给你的cmd invokation.在以下情况下您不需要它:

> ruby -s script_with_switches.rb -agreed
> So do I!
Run Code Online (Sandbox Code Playgroud)

缺点是你搞乱全局变量并且只有逻辑真/假值.

您可以从环境变量访问值:

> FIRST_NAME='Andy Warhol' ruby -e 'puts ENV["FIRST_NAME"]'
> Andy Warhol
Run Code Online (Sandbox Code Playgroud)

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

> export FIRST_NAME='Andy Warhol'
> ruby -e 'puts ENV["FIRST_NAME"]'
Run Code Online (Sandbox Code Playgroud)

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

至少你可以使用getoptlongoptparse实现一个选项解析器.

快乐的黑客!