source

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

factcode 2023. 6. 3. 08:46
반응형

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

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

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

이와 같은 것:

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

운전대를 바꾸지 말고 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)

안타깝게도 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!

에 하시기 바랍니다.--스위치, 그렇지 않으면 루비는 존재하지 않는 옵션에 대해 불평할 것입니다.-agreed로 전달합니다.다음과 같은 경우에는 필요하지 않습니다.

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

단점은 전역 변수를 잘못 사용하고 논리적 참/거짓 값만 가지고 있다는 것입니다.

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

> 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를 사용하여 옵션 파서를 구현할 수 있습니다.

해피 해킹!

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 파일을 사용하는 것이라고 생각합니다.

사용해 볼 수도 있습니다.cliqr그것은 꽤 새롭고 활발한 발전이 없습니다.그러나 사용할 수 있는 안정적인 릴리스가 있습니다.다음은 git repo입니다: https://github.com/anshulverma/cliqr

예제 폴더를 조사하여 사용 방법에 대한 아이디어를 얻습니다.

명령줄에서 이 코드를 실행하고 N:

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

가장 사소한 경우가 아닌 한, 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>"=>[]}

맛있게 드세요!

console_runner gem을 사용해 보십시오.이 보석은 명령행에서 순수한 루비 코드를 실행할 수 있게 해줍니다.코드에 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!

언급URL : https://stackoverflow.com/questions/4244611/pass-variables-to-ruby-script-via-command-line

반응형