Pasar variables a Ruby script a través de la línea de comandos


He instalado RubyInstaller en Windows y estoy ejecutando IMAP Sync pero necesito usarlo para sincronizar cientos de cuentas. Si pudiera pasar estas variables a través de la línea de comandos podría automatizar todo el proceso mejor.

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

# Destination server connection info.
DEST_NAME = '[email protected]'
DEST_HOST = 'imap.gmail.com'
DEST_PORT = 993
DEST_SSL  = true
DEST_USER = '[email protected]'
DEST_PASS = 'password'
Author: the Tin Man, 2010-11-22

6 answers

Algo como esto:

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

Entonces

$ ./test.rb "test1 test2"

O

v1 = ARGV[0]
v2 = ARGV[1]
puts v1       #prints test1
puts v2       #prints test2
 414
Author: demas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-02 23:17:00

No reinventes la rueda; echa un vistazo a la librería way-cool de Ruby OptionParser.

Ofrece análisis de indicadores/interruptores, parámetros con valores opcionales o requeridos, puede analizar listas de parámetros en una sola opción y puede generar su ayuda para usted.

Además, si alguna de la información que se pasa es bastante estática, eso no cambia entre corridas, colóquela en un archivo YAML que se analiza. De esa manera puede tener cosas que cambian cada vez en la línea de comandos, y cosas que cambian ocasionalmente configuradas fuera de su código. Esa separación de datos y código es buena para el mantenimiento.

Aquí hay algunas muestras para jugar:

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

Este es un archivo YAML de ejemplo si sus destinos son bastante estáticos:

--- 
dest_name: [email protected]
dest_host: imap.gmail.com
dest_port: 993
dest_ssl: true
dest_user: [email protected]
dest_pass: password

Esto le permitirá generar fácilmente un archivo YAML:

require 'yaml'

yaml = {
  'dest_name' => '[email protected]',
  'dest_host' => 'imap.gmail.com',
  'dest_port' => 993,
  'dest_ssl'  => true,
  'dest_user' => '[email protected]',
  'dest_pass' => 'password'
}

puts YAML.dump(yaml)
 173
Author: the Tin Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-07 21:43:03

Desafortunadamente, Ruby no soporta tal mecanismo de paso como por ejemplo AWK:

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

Significa que no puede pasar valores con nombre directamente a su script.

Usar las opciones de cmd puede ayudar:

> 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 almacena todos los argumentos cmd en el array ARGV, el scriptname se puede capturar usando la variable $PROGRAM_NAME.

La desventaja obvia es que depende del orden de los valores.

Si solo necesita conmutadores booleanos use la opción -s del Intérprete de Ruby:

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

Tenga en cuenta el interruptor --, de lo contrario Ruby se quejará de una opción inexistente -agreed, así que pásela como un interruptor a su invocación cmd. No lo necesita en el siguiente caso:

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

La desventaja es que usted se mete con variables globales y solo tiene valores lógicos verdadero/falso.

Puede acceder a los valores de las variables de entorno:

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

Inconvenientes están presentes aquí, usted tiene que establecer todas las variables antes de la invocación de script (solo para tu proceso ruby) o para exportarlos (shells como BASH):

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

En este último caso, sus datos serán legibles para todos en la misma sesión de shell y para todos los subprocesos, lo que puede ser una grave implicación de seguridad.

Y al menos puedes implementar un analizador de opciones usando getoptlong y optparse.

Feliz hackeo!

 25
Author: Andrei Beliankou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-19 11:04:09

A menos que sea el caso más trivial, solo hay una forma sana de usar las opciones de la línea de comandos en Ruby. Se llama docopt y se documenta aquí.

Lo que es sorprendente con él, es su simplicidad. Todo lo que tiene que hacer, es especificar el texto de "ayuda" para su comando. Lo que escribas allí será analizado automáticamente por el standalone (!) ruby library.

Del ejemplo :

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

La salida:

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

Disfrute!

 2
Author: not2qubit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-05 23:07:07

También puedes probar cliqr. Es bastante nuevo y en desarrollo activo. Pero hay versiones estables listas para ser utilizadas. Aquí está el repositorio de git: https://github.com/anshulverma/cliqr

Busque en la carpeta de ejemplo para tener una idea de cómo se puede usar.

 1
Author: nuaavee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-18 17:12:26

Ejecute este código en la línea de comandos e introduzca el valor de N:

N  = gets; 1.step(N.to_i, 1) { |i| print "hello world\n" }
 1
Author: tin tin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 00:34:31