명령 행을 통해 변수를 Ruby 스크립트로 전달


275

Windows에 RubyInstaller를 설치했으며 IMAP 동기화를 실행하고 있지만 수백 개의 계정을 동기화하려면이를 사용해야합니다. 명령 줄을 통해 이러한 변수를 전달할 수 있다면 전체 프로세스를 더 잘 자동화 할 수 있습니다.

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

1
이 인기있는 질문을 실제 질문 으로 편집하는 것이 좋습니다.
not2qubit

답변:


465

이 같은:

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

84
다른 언어들처럼 ARGV [0]이 프로그램 이름을 가리 키지 않는다는 것을 분명히 지적하고 싶습니다. 프로그램 이름을 얻으려면 stackoverflow.com/questions/4834821/…를
Sander Mertens

3
"test1 test2"는 하나의 인수가 아닌가?
wuliwong

다음과 같이 실행하려면 파일 #!/usr/bin/env ruby위에 추가해야합니다 .rb../test.rb
xamenrax

191

바퀴를 재발 명하지 마십시오. 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']

대상이 정적 인 경우 샘플 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

이렇게하면 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)

2
OptParse 링크가 종료되었습니다. ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/…를
Casey

7
훌륭한 답변; 옵션 구문 분석이 완료된 후 ARGV피연산자 (있는 경우), 나머지 NON 옵션 인수 만 포함 한다는 점을 추가 할 가치가 있습니다 .
mklement0

27

불행히도 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변수를 사용하여 캡처 할 수 있습니다 .

명백한 단점은 값의 순서에 의존한다는 것입니다.

부울 스위치 만 필요한 경우 -sRuby 인터프리터 옵션 을 사용하십시오 .

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

단점은 전역 변수를 망쳐 놓고 논리적 참 / 거짓 값만 갖는 것입니다.

환경 변수에서 값에 액세스 할 수 있습니다.

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

단점은 여기에 있으며 스크립트 호출 전에 모든 변수를 설정하거나 (루비 프로세스에만 해당) 내 보내야합니다 (BASH와 같은 쉘).

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

후자의 경우 동일한 셸 세션의 모든 사용자와 모든 하위 프로세스에서 데이터를 읽을 수 있으며 이는 심각한 보안 문제가 될 수 있습니다.

적어도 getoptlongoptparse를 사용하여 옵션 파서를 구현할 수 있습니다 .

행복한 해킹!


1

시도해 볼 수도 있습니다 cliqr. 꽤 새롭고 적극적으로 개발 중입니다. 그러나 사용할 준비가 된 안정된 릴리스가 있습니다. 여기 자식 저장소가 있습니다 : https://github.com/anshulverma/cliqr

사용 방법에 대한 아이디어를 얻으려면 예제 폴더를 살펴보십시오.


0

명령 행에서이 코드를 실행하고 N 값을 입력하십시오.

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

0

가장 사소한 경우가 아니라면 Ruby에서 명령 행 옵션을 사용하는 방법은 단 하나뿐입니다. docopt 라고 하며 여기에 문서화되어 있습니다 .

놀라운 점은 단순하다는 것입니다. 명령에 대한 "도움말"텍스트를 지정하기 만하면됩니다. 거기에 작성한 내용은 독립형 (!) 루비 라이브러리에 의해 자동 구문 분석됩니다 .

로부터 :

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

즐겨!


0

console_runner gem을 사용해보십시오 . 이 gem은 명령 행에서 순수한 Ruby 코드를 실행 가능하게합니다. 코드에 YARD 주석을 추가하기 만하면 됩니다.

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

tl; dr

나는 이것이 오래 되었다는 것을 알고 있지만 여기서 getoptlong 은 언급되지 않았 으며 오늘날 명령 줄 인수를 구문 분석하는 가장 좋은 방법 일 것입니다.


명령 줄 인수 구문 분석

getoptlong을 강력히 권장 합니다 . 사용하기 쉽고 매력처럼 작동합니다. 위의 링크에서 추출한 예는 다음과 같습니다.

require 'getoptlong'

opts = GetoptLong.new(
    [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
    [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
)

dir = nil
name = nil
repetitions = 1
opts.each do |opt, arg|
    case opt
        when '--help'
            puts <<-EOF
hello [OPTION] ... DIR

-h, --help:
     show help

--repeat x, -n x:
     repeat x times

--name [name]:
     greet user by name, if name not supplied default is John

DIR: The directory in which to issue the greeting.
            EOF
        when '--repeat'
            repetitions = arg.to_i
        when '--name'
            if arg == ''
                name = 'John'
            else
                name = arg
            end
    end
end

if ARGV.length != 1
    puts "Missing dir argument (try --help)"
    exit 0
end

dir = ARGV.shift

Dir.chdir(dir)
for i in (1..repetitions)
    print "Hello"
    if name
        print ", #{name}"
    end
    puts
end

당신은 이것을 이렇게 부를 수 있습니다 ruby hello.rb -n 6 --name -- /tmp

OP가하려고하는 것

이 경우 가장 좋은 옵션은 이 답변에서 제안한대로 YAML 파일을 사용 하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.