Ruby 2.4

GetoptLong

class GetoptLong

Parent:Object

GetoptLong类允许您像GNU getopt_long() C库调用一样解析命令行选项。但是请注意,GetoptLong是一个纯粹的Ruby实现。

GetoptLong允许POSIX风格的选项--file以及单个字母选项-f

空选项--(两个减号)用于结束选项处理。如果选项具有可选参数,这可能尤其重要。

以下是一个简单的使用示例:

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

示例命令行:

hello -n 6 --name -- /tmp

常量

ARGUMENT_FLAGS

参数标志。

ORDERINGS

Orderings.

STATUS_TERMINATED

属性

errorR

检查选项处理是否失败。

error?R

检查选项处理是否失败。

orderingR

返回ordering。

quietRW

Set/Unset `quiet' mode.

quiet?RW

Set/Unset `quiet' mode.

公共类方法

new(*arguments) Show source

设置选项处理。

支持的选项作为数组数组传递给new()。每个子数组包含任意数量的带有相同含义的字符串选项名称,以及以下标志之一:

GetoptLong::NO_ARGUMENT

选项没有参数。

GetoptLong::REQUIRED_ARGUMENT

选项总是需要一个参数。

GetoptLong::OPTIONAL_ARGUMENT

选项可能会或可能不会引发争论。

第一个选项名称被认为是首选(规范)名称。除此之外,每个子阵列的元素可以以任何顺序排列。

# File lib/getoptlong.rb, line 128 def initialize(*arguments) # # Current ordering. # if ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = PERMUTE end # # Hash table of option names. # Keys of the table are option names, and their values are canonical # names of the options. # @canonical_names = Hash.new # # Hash table of argument flags. # Keys of the table are option names, and their values are argument # flags of the options. # @argument_flags = Hash.new # # Whether error messages are output to $stderr. # @quiet = false # # Status code. # @status = STATUS_YET # # Error code. # @error = nil # # Error message. # @error_message = nil # # Rest of catenated short options. # @rest_singles = '' # # List of non-option-arguments. # Append them to ARGV when option processing is terminated. # @non_option_arguments = Array.new if 0 < arguments.length set_options(*arguments) end end

公共实例方法

each() { |option_name, option_argument| ... } Show source

迭代版本'get'。

该块被重复调用两个参数:第一个是选项名称。第二个是它后面的论点(如果有的话)。例如:('-opt','value')

选项名称始终转换为原始选项中给出的第一个(首选)名称:: new。

# File lib/getoptlong.rb, line 600 def each loop do option_name, option_argument = get_option break if option_name == nil yield option_name, option_argument end end

另外别名为:each_option

each_option()

each\_option' is an alias ofeach'.

Alias for: each

error_message() Show source

以POSIX定义的格式返回相应的错误消息。如果没有发生错误,则返回nil。

# File lib/getoptlong.rb, line 411 def error_message return @error_message end

get() Show source

获取下一个选项名称及其参数,作为两个元素的数组。

选项名称始终转换为原始选项中给出的第一个(首选)名称:: new。

Example: '–option', 'value'

如果处理完成(由STATUS_TERMINATED确定),则返回nil。

# File lib/getoptlong.rb, line 426 def get option_name, option_argument = nil, '' # # Check status. # return nil if @error != nil case @status when STATUS_YET @status = STATUS_STARTED when STATUS_TERMINATED return nil end # # Get next option argument. # if 0 < @rest_singles.length argument = '-' + @rest_singles elsif (ARGV.length == 0) terminate return nil elsif @ordering == PERMUTE while 0 < ARGV.length && ARGV[0] !~ /^-./ @non_option_arguments.push(ARGV.shift) end if ARGV.length == 0 terminate return nil end argument = ARGV.shift elsif @ordering == REQUIRE_ORDER if (ARGV[0] !~ /^-./) terminate return nil end argument = ARGV.shift else argument = ARGV.shift end # # Check the special argument `--'. # `--' indicates the end of the option list. # if argument == '--' && @rest_singles.length == 0 terminate return nil end # # Check for long and short options. # if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0 # # This is a long style option, which start with `--'. # pattern = $1 if @canonical_names.include?(pattern) option_name = pattern else # # The option `option_name' is not registered in `@canonical_names'. # It may be an abbreviated. # matches = [] @canonical_names.each_key do |key| if key.index(pattern) == 0 option_name = key matches << key end end if 2 <= matches.length set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") elsif matches.length == 0 set_error(InvalidOption, "unrecognized option `#{argument}'") end end # # Check an argument to the option. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length option_argument = ARGV.shift else set_error(MissingArgument, "option `#{argument}' requires an argument") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end elsif argument =~ /=(.*)$/ set_error(NeedlessArgument, "option `#{option_name}' doesn't allow an argument") end elsif argument =~ /^(-(.))(.*)/ # # This is a short style option, which start with `-' (not `--'). # Short options may be catenated (e.g. `-l -g' is equivalent to # `-lg'). # option_name, ch, @rest_singles = $1, $2, $3 if @canonical_names.include?(option_name) # # The option `option_name' is found in `@canonical_names'. # Check its argument. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length option_argument = ARGV.shift else # 1003.2 specifies the format of this message. set_error(MissingArgument, "option requires an argument -- #{ch}") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end end else # # This is an invalid option. # 1003.2 specifies the format of this message. # if ENV.include?('POSIXLY_CORRECT') set_error(InvalidOption, "invalid option -- #{ch}") else set_error(InvalidOption, "invalid option -- #{ch}") end end else # # This is a non-option argument. # Only RETURN_IN_ORDER fell into here. # return '', argument end return @canonical_names[option_name], option_argument end

另外别名为:get_option

get_option()

get\_option' is an alias ofget'.

别名为:get

ordering=(ordering) Show source

设置选项和参数排序的处理。如果选项处理已经开始,则会引发RuntimeError。

提供的值必须是GetoptLong::ORDERINGS的成员。它改变了选项的处理过程,如下所示:

REQUIRE_ORDER :

选项必须在非选项之前发生。

处理选项只要遇到一个没有选择适当选项标志的单词,就立即结束。

例如,如果-a和-b是不带参数的选项,解析命令行参数'-a one -b two'将导致ARGV中留下'one','-b','two'并且仅将('-a','')作为选项/参数对处理。

如果设置了环境变量POSIXLY_CORRECT,则这是默认排序。(这是为了与GNU getopt_long兼容。)

PERMUTE :

选项可以发生在解析的命令行中的任何地方。这是默认行为。

可以解释为选项(有或没有参数)的每个单词序列都被视为一个选项;非选项字被跳过。

例如,如果-a不需要参数并且-b可选地接受参数,则解析'-a一个-b两个三'将导致('-a','')和('-b','two ')作为选项/参数对处理,并且'一','三'留在ARGV中。

如果排序设置为PERMUTE,但设置了环境变量POSIXLY_CORRECT,则使用REQUIRE_ORDER。这是为了与GNU getopt_long兼容。

RETURN_IN_ORDER :

命令行上的所有单词都作为选项进行处理。没有短或长选项标志的单词作为参数传递,选项为''(空字符串)。

例如,如果-a需要一个参数,但-b不需要,则'-a一个-b二三个'的命令行将导致('-a','一个')的选项/ arg对('-b ',''),('','two'),('','3')正在被处理。

# File lib/getoptlong.rb, line 237 def ordering=(ordering) # # The method is failed if option processing has already started. # if @status != STATUS_YET set_error(ArgumentError, "argument error") raise RuntimeError, "invoke ordering=, but option processing has already started" end # # Check ordering. # if !ORDERINGS.include?(ordering) raise ArgumentError, "invalid ordering `#{ordering}'" end if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = ordering end end

set_options(*arguments) Show source

设置选项。采用与:: new相同的参数。

如果选项处理已经开始,则引发RuntimeError。

# File lib/getoptlong.rb, line 270 def set_options(*arguments) # # The method is failed if option processing has already started. # if @status != STATUS_YET raise RuntimeError, "invoke set_options, but option processing has already started" end # # Clear tables of option names and argument flags. # @canonical_names.clear @argument_flags.clear arguments.each do |arg| if !arg.is_a?(Array) raise ArgumentError, "the option list contains non-Array argument" end # # Find an argument flag and it set to `argument_flag'. # argument_flag = nil arg.each do |i| if ARGUMENT_FLAGS.include?(i) if argument_flag != nil raise ArgumentError, "too many argument-flags" end argument_flag = i end end raise ArgumentError, "no argument-flag" if argument_flag == nil canonical_name = nil arg.each do |i| # # Check an option name. # next if i == argument_flag begin if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/ raise ArgumentError, "an invalid option `#{i}'" end if (@canonical_names.include?(i)) raise ArgumentError, "option redefined `#{i}'" end rescue @canonical_names.clear @argument_flags.clear raise end # # Register the option (`i') to the `@canonical_names' and # `@canonical_names' Hashes. # if canonical_name == nil canonical_name = i end @canonical_names[i] = canonical_name @argument_flags[i] = argument_flag end raise ArgumentError, "no option name" if canonical_name == nil end return self end

terminate() Show source

显式终止选项处理。

# File lib/getoptlong.rb, line 357 def terminate return nil if @status == STATUS_TERMINATED raise RuntimeError, "an error has occurred" if @error != nil @status = STATUS_TERMINATED @non_option_arguments.reverse_each do |argument| ARGV.unshift(argument) end @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil return self end

terminated?() Show source

如果选项处理已终止,则返回true,否则返回false。

# File lib/getoptlong.rb, line 377 def terminated? return @status == STATUS_TERMINATED end

受保护的实例方法

set_error(type, message) Show source

设置一个错误(受保护的方法)。

# File lib/getoptlong.rb, line 384 def set_error(type, message) $stderr.print("#{$0}: #{message}\n") if !@quiet @error = type @error_message = message @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil raise type, message end