web-dev-qa-db-fra.com

Passer les variables au script Ruby par le biais de la ligne de commande

J'ai installé RubyInstaller sur Windows et j'utilise IMAP Sync mais je dois l'utiliser pour synchroniser des centaines de comptes. Si je pouvais lui transmettre ces variables via la ligne de commande, je pourrais automatiser le processus dans son ensemble.

# 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'
260
Robinicks

Quelque chose comme ça:

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

ensuite

$ ./test.rb "test1 test2"

ou

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

Ne réinventez pas la roue; Découvrez la façon géniale de Ruby OptionParser .

Il offre une analyse des indicateurs/commutateurs, des paramètres avec des valeurs facultatives ou obligatoires, peut analyser des listes de paramètres dans une seule option et peut générer votre aide pour vous.

De plus, si l'une des informations que vous transmettez est plutôt statique, cela ne changera pas entre les exécutions, insérez-le dans un fichier YAML qui sera analysé. De cette façon, vous pouvez avoir des choses qui changent à chaque fois sur la ligne de commande et des choses qui changent de temps en temps configurées en dehors de votre code. Cette séparation des données et du code est agréable pour la maintenance.

Voici quelques exemples pour jouer avec:

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

Ceci est un exemple de fichier YAML si vos destinations sont plutôt statiques:

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

Cela vous permettra de générer facilement un fichier 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)
184
the Tin Man

Malheureusement, Ruby ne prend pas en charge un mécanisme de passage tel que, par exemple. AWK:

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

Cela signifie que vous ne pouvez pas transmettre directement les valeurs nommées dans votre script.

Utiliser les options de cmd peut aider:

> 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 stocke tous les arguments cmd dans le tableau ARGV. Le nom du script lui-même peut être capturé à l'aide de la variable $PROGRAM_NAME.

L'inconvénient évident est que vous dépendez de l'ordre des valeurs.

Si vous n’avez besoin que de commutateurs booléens, utilisez l’option -s de l’interprète Ruby:

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

Veuillez noter le commutateur --, sinon Ruby se plaindra d'une option inexistante -agreed, alors transmettez-le comme un commutateur à votre invocation de commande. Vous n'en avez pas besoin dans le cas suivant:

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

L'inconvénient est que vous manipulez les variables globales et que vous n'avez que des valeurs logiques vrai/faux.

Vous pouvez accéder aux valeurs des variables d'environnement:

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

Les inconvénients sont présents ici, vous devez définir toutes les variables avant l'appel du script (uniquement pour votre processus Ruby) ou les exporter (shells comme BASH):

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

Dans ce dernier cas, vos données seront lisibles par tout le monde dans la même session Shell et par tous les sous-processus, ce qui peut être une grave implication pour la sécurité.

Et au moins, vous pouvez implémenter un analyseur d'options en utilisant getoptlong et optparse .

Joyeux piratage!

26
Andrei Beliankou

À moins que ce ne soit le cas le plus trivial, Ruby ne dispose que d’un moyen sain d’utiliser les options de ligne de commande. Il s'appelle docopt et documenté ici .

Ce qui est incroyable avec ça, c’est sa simplicité. Tout ce que vous avez à faire est de spécifier le texte "aide" de votre commande. Ce que vous écrivez ici sera alors automatiquement analysé par le autonome (!) Ruby bibliothèque.

De la exemple :

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

Le résultat:

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

Prendre plaisir!

1
not2qubit

Exécutez ce code sur la ligne de commande et entrez la valeur de N:

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

Vous pouvez également essayer cliqr. Sa jolie nouvelle et en développement actif. Mais il existe des versions stables prêtes à être utilisées. Voici le dépôt Git: https://github.com/anshulverma/cliqr

Regardez dans le dossier des exemples pour avoir une idée de la façon dont il peut être utilisé.

1
nuaavee

Vous devriez essayer console_runner gem. Ce bijou rend votre code pur Ruby exécutable à partir de la ligne de commande. Tout ce dont vous avez besoin est d'ajouter YARD annotations à votre code:

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

Puis lancez le depuis la console:

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