首页 > 代码库 > Ruby stdlib 学习 —— OptionParser

Ruby stdlib 学习 —— OptionParser

http://ruby-doc.org/stdlib-2.3.3/libdoc/optparse/rdoc/OptionParser.html#method-c-new
 
  阅读lib的文档,做个笔记。OptionParser 这个类用于,在写一些command line工具的时候,设置命令行参数选项。GetoptLong有类似的功能,不过文中建议使用OptionParser.
一、例:简单示例 (主要是入个门,顺便演示了下不带参数的选项该怎么处理,像-v, -f 那种))
技术分享
 1 #直接存成test.rb, 运行 ruby test.rb -v somethingnouse 能正常运行
 2 #运行 ruby test.rb -v somethingnouse -s,因为没有设置-s的选项处理,
 3 #会报错"invalid option: -s (OptionParser::InvalidOption)"
 4 require optparse
 5  
 6 p ARGV # => ["-v", "somethingnouse"]
 7 options = {} #自己设置用来接收输入参数的hash,用数组应该也可以,随便,
 8              #也可以说和OptionParser没什么关系
 9 OptionParser.new do |opts|
10   opts.banner = "Usage: example.rb [options]"
11  
12   opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| #选项-v后面没有值,看来有的话会赋值成true
13     puts "value of v"#不写-v选项的话程序根本不到这一行,可以理解成if has "-v" 这种感觉吧
14     puts v #=> true
15     options[:verbose] = v #这里写一些功能上的code
16   end
17 end.parse! #shift一个参数, Code:a = [1,2,3]; a.shift ##output=> a=[2,3] 应该是类似这种机制吧,细节没看
18  
19 p options #{:verbose=>true}
20 p ARGV #["somethingnouse"]
View Code
 
二、例:生成help
基本就是边调试边注释来学习的。在文档里例子的基础上改了一些小地方用作调试。
技术分享
 1 require optparse
 2  
 3 Options = Struct.new(:name)
 4  
 5 class Parser
 6   def self.parse(options)
 7     args = Options.new("world") #Struct类args的参数name默认值为"world"
 8  
 9     opt_parser = OptionParser.new do |opts| #开始使用OptionParser类处理参数
10       opts.banner = "Usage:example.rb [option]" #输出help时最上面那一行
11  
12       opts.on("-n NAME", "--name=NAME", "Name to say hello to") do |n|
13       #输入参数选项为-n时,需要带参数NAME, 用法:ruby test.rb --name="A puppy"
14       #例子里-nNAME之间没有空格,测了一下参数写成"-nDog"是好用的。
15       #同样,长参数--name写成--name NAME,而在调用的时候 ruby test.rb --name="A puppy"也成立,非常灵活
16         args.name = n #这里其实就是把参数值传到别的地方去,加工,打印,随你怎么处理
17         puts n       
18         puts "#{ARGV}" #可以用例查看一下ARGV的变化,命令为 ruby test.rb -n Dog -h 运行时,这里输出["-h"]
19                        #和预想的有点出入,有时间可以看看OptionParser的Code深入理解一下
20       end
21  
22       opts.on("-h", "--help", "Prints this help") do
23         puts opts #打印所有的opts内容,其实就是我们设置的每项opt.on的加上banner
24         #exit #打印完help就退出了,不处理其他参数。注意exit是退出程序
25         #比如我在line17 打印了name的值。如果我运行 ruby test.rb -n Dog -h
26         #output:
27         #Dog
28         #Usage:example.rb [option]
29         #-n, --name=NAME                  Name to say hello to
30         #-h, --help                       Prints this help
31         #显然先处理了 -n 选项,又处理了-h再退出的
32  
33       end
34     end
35  
36     opt_parser.parse!(options) #!=>shift 继续处理下一个参数
37     return args  #看到这里就明白,在实际应用中,可以用这个Struct来收集所有传入的参数值
38   end
39 end
40  
41 #options = Parser.parse %w[-h] #%w 用于表示其中元素被引号括起的数组,元素用空格分离。如 %w[a b] => ["a", "b"]
42 options = Parser.parse ARGV #直接处理运行命令行传入的参数
43 puts options
View Code
 
  顺便搜了一下ruby的选项源码:就是ruby --help列举的那些:https://github.com/ruby/ruby/blob/ruby_2_3/ruby.c 好像也没用什么库之类的(主要搂了一眼没看着include<getopt.h>),应该是直接宏+printf(这几行code位置line224-237):
技术分享
 1 #define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help)
 2 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
 3 for (i = 0; i < num; ++i)
 4 SHOW(usage_msg[i]);
 5 if (!help) return;
 6 for (i = 0; i < numberof(help_msg); ++i)
 7 SHOW(help_msg[i]);
 8 puts("Features:");
 9 for (i = 0; i < numberof(features); ++i)
10 SHOW(features[i]);
11 }
View Code
  用宏定义函数这方面的知识我基本为0。有兴趣可以观摩一下。
 
三、参数有一些内置类型可以直接拿来用
Date – Anything accepted by Date.parse
DateTime – Anything accepted by DateTime.parse
Time – Anything accepted by Time.httpdate or Time.parse
URI – Anything accepted by URI.parse
Shellwords – Anything accepted by Shellwords.shellwords
String – Any non-empty string
Integer – Any integer. Will convert octal. (e.g. 124, -3, 040)
Float – Any float. (e.g. 10, 3.14, -100E+13)
Numeric – Any integer, float, or rational (1, 3.4, 1/3)
DecimalInteger -- Like Integer, but no octal format.
OctalInteger -- Like Integer, but no decimal format.
DecimalNumeric -- Decimal integer or float.
TrueClass – Accepts ‘+, yes, true, -, no, false’ and defaults as true
FalseClass – Same as TrueClass, but defaults to false
Array – Strings separated by ‘,’ (e.g. 1,2,3)
Regexp – Regular expressions. Also includes options.
 
一个使用time的例子:
技术分享
 1 require optparse
 2 require optparse/time
 3  
 4 OptionParser.new do |parser|
 5   #例子比较简单,重点应该就在第三个参数,输入之后相关类会自动解析?
 6   parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
 7     p time
 8   end
 9 end.parse!
10 # 比如运行:ruby test.rb  -t 2000-1-1
11 # output: 2000-01-01 00:00:00 +0800
12 # time 被自动处理了
View Code
 
四 op.accept用法。
理解上可以用accept关联任何自定义类型的实例,再通过OptionParser和外界交互。文档里举得这个例子,可以联想到gem install 的用法。比如:gem install libA。gem 要去查询libA的安装路径时,每个lib和安装路径就是key和value的关系。如果找不到这个libA,当然也就报错了。先这么理解着。
还没注释,待整理。
 1 require optparse
 2  
 3 User = Struct.new(:id, :name)
 4  
 5 def find_user id
 6   not_found = ->{ raise "No User Found for id #{id}" }
 7   [ User.new(1, "Sam"),
 8     User.new(2, "Gandalf") ].find(not_found) do |u|
 9     u.id == id
10   end
11 end
12  
13 op = OptionParser.new
14   op.accept(User) do |user_id|
15     find_user user_id.to_i
16   end
17   op.on("--user ID", User) do |user|
18     puts user
19   end
20 op.parse!

 

 
 
 

Ruby stdlib 学习 —— OptionParser