Przekazywanie zmiennych do skryptu Ruby za pomocą wiersza poleceń

Zainstalowałem RubyInstaller na Windows i uruchamiam IMAP Sync , ale muszę go użyć do synchronizacji setek kont. Gdybym mógł przekazać te zmienne do niego za pomocą wiersza poleceń mógłbym lepiej zautomatyzować cały proces.

# 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

Coś takiego:

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

Then

$ ./test.rb "test1 test2"

Lub

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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-02 23:17:00

Nie odkrywaj koła na nowo; sprawdź bibliotekę OptionParser Ruby ' s way-cool.

Oferuje parsowanie FLAG/przełączników, parametrów z opcjonalnymi lub wymaganymi wartościami, może parsować listy parametrów w jedną opcję i może wygenerować pomoc dla Ciebie.

Ponadto, jeśli któraś z Twoich informacji jest dość statyczna, to nie zmienia się między uruchomieniami, umieść ją w pliku YAML, który zostanie przetworzony. W ten sposób możesz mieć rzeczy, które zmieniają się za każdym razem w wierszu poleceń, i rzeczy, które zmieniają się od czasu do czasu skonfigurowane poza kodem. Ta separacja danych i kodu jest dobra do konserwacji.

Oto kilka próbek do zabawy:

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

Jest to przykładowy plik YAML, jeśli miejsce docelowe jest dość statyczne:

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

To pozwoli Ci łatwo wygenerować plik 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 21:43:03

Niestety, Ruby nie obsługuje takiego mechanizmu przekazywania jak np. AWK:

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

Oznacza to, że nie można przekazywać nazwanych wartości bezpośrednio do skryptu.

Użycie opcji cmd może pomóc:

> 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 przechowuje wszystkie argumenty cmd w tablicy ARGV, sama nazwa skryptu może być przechwycona za pomocą zmiennej $PROGRAM_NAME.

Oczywistą wadą jest to, że zależy od kolejności wartości.

Jeśli potrzebujesz tylko przełączników Boolean użyj opcji -s z Interpreter Ruby:

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

Zwróć uwagę na przełącznik --, W Przeciwnym Razie Ruby będzie narzekać na nieistniejącą opcję -agreed, więc przekaż ją jako przełącznik do wywołania cmd. Nie potrzebujesz go w następującym przypadku:

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

Wadą jest to, że zadzierasz ze zmiennymi globalnymi i masz tylko logiczne wartości prawda / fałsz.

Możesz uzyskać dostęp do wartości ze zmiennych środowiskowych:

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

Wady są obecne tutaj, musisz ustawić wszystkie zmienne przed wywołanie skryptu (tylko dla Twojego procesu ruby) lub ich eksport (powłoki takie jak BASH):

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

W tym drugim przypadku, Twoje dane będą czytelne dla wszystkich w tej samej sesji powłoki i dla wszystkich podprocesów, co może być poważną implikacją bezpieczeństwa.

I przynajmniej możesz zaimplementować parser opcji używając getoptlongi optparse.

Szczęśliwego hakowania!
 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-19 11:04:09

O ile nie jest to najbardziej trywialny przypadek, jest tylko jeden rozsądny sposób użycia opcji wiersza poleceń w Rubim. Nazywa się docopt i udokumentowane TUTAJ.

To, co jest w nim niesamowite, to prostota. wszystko, co musisz zrobić, to podać tekst "pomoc" dla Twojego polecenia. to co tam napiszesz zostanie automatycznie parsowane przez standalone (!) biblioteka ruby.

Z przykład :

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

Wyjście:

$ ./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>"=>[]}
Smacznego!
 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/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 23:07:07

Możesz również wypróbować cliqr. Jest całkiem nowy i w aktywnym rozwoju. Ale są stabilne wydania gotowe do użycia. Oto repo git: https://github.com/anshulverma/cliqr

Zajrzyj do przykładowego folderu, aby dowiedzieć się, jak można go użyć.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 17:12:26

Uruchom ten kod w wierszu poleceń i wprowadź wartość 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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 00:34:31