web-dev-qa-db-ja.com

コマンドライン経由でRubyスクリプトに変数を渡す

私はWindowsにRubyInstallerをインストールし、私は IMAP Sync を実行していますが、何百ものアカウントを同期するためにそれを使う必要があります。コマンドラインでこれらの変数を渡すことができれば、プロセス全体をより自動化することができます。

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

このようなもの:

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
442
demas

車輪を改造しないでください。 Rubyのway-cool 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: [email protected]
dest_Host: imap.gmail.com
dest_port: 993
dest_ssl: true
dest_user: [email protected]
dest_pass: password

これにより、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)
181
the Tin Man

残念ながら、Rubyはこのような受け渡しメカニズムをサポートしていません。 AWK:

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

つまり、名前付きの値をスクリプトに直接渡すことはできません。

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

Rubyはすべてのcmd引数をARGV配列に格納します。スクリプト名自体は$PROGRAM_NAME変数を使用して取得できます。

明らかな不利な点は、値の順序に依存しているということです。

ブールスイッチだけが必要な場合は、Rubyインタプリタのオプション-sを使用してください。

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

--スイッチに注意してください。そうでなければ、Rubyは存在しないオプション-agreedについて文句を言うでしょう、それであなたのcmd呼び出しへのスイッチとしてそれを渡します。次の場合は必要ありません。

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

不利な点は、あなたがグローバル変数を台無しにし、論理的なtrue/false値しか持っていないことです。

環境変数から値にアクセスできます。

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

欠点はここにあります、あなたはスクリプト呼び出しの前にすべての変数を設定しなければなりません(あなたのRubyプロセスのためにだけ)、またはそれらをエクスポートしなければなりません(BASHのようなシェル):

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

後者の場合、あなたのデータは、同じシェルセッション内の全員およびすべてのサブプロセスに対して読み取り可能になりますが、これは深刻なセキュリティ上の問題となります。

そして少なくとも getoptlongoptparse を使ってオプションパーサーを実装することができます。

ハッピーハッキング!

25

それが最も些細な場合でない限り、Rubyでコマンドラインオプションを使うための唯一の正しい方法があります。これは docopt と呼ばれ、ここでは と記録されます

それで素晴らしいのは、それがシンプルだということです。 あなたがしなければならないのは、あなたのコマンドのための「ヘルプ」テキストを指定することだけです。 そこに書いたものはstandalone(!)Rubyライブラリによって自動解析されます。

の例から

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

楽しい!

1
not2qubit

コマンドラインでこのコードを実行してNの値を入力します。

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

cliqrを試すこともできます。そのかなり新しく、活発な開発中です。しかし、すぐに使える安定版リリースがあります。これがgitリポジトリです: https://github.com/anshulverma/cliqr

Exampleフォルダを調べて、それがどのように使用されるのかを考えてください。

1
nuaavee

あなたは console_runner gemを試すべきです。このgemはあなたの純粋なRubyコードをコマンドラインから実行可能にします。必要なのは、コードに ヤード の注釈を追加することだけです。

# @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!
0
Yuri Karpovich