部署 Ruby 命令行参数解析如何禁止解释通配符?

suupic · 2012年05月10日 · 最后由 xzgyb 回复于 2012年05月10日 · 4502 次阅读

写一个脚本,要输入文件通配符 但是试过 mixlib-cli、optparse、slop,发现都存在这样一个问题: 当命令参数输入的通配符可以匹配存在的文件路径时,通配符会被自动解释成匹配的文件列表 例如:

require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-f", "--file FILE", "File ") do |f|
    options[:file] = f
  end
end.parse!

p options
p options[:file].class
p options[:file]                                                                                                                                                            

运行结果

ruby t.rb -f dist1/*.*
{:file=>"dist1/*.*"}
String
"dist1/*.*"
# ruby t.rb -f dist/*.* 
{:file=>"dist/dist.rb"}
String
"dist/dist.rb"

可见,当参数为不存在的目录 dist1,通配符不被解释 当参数为存在的目录 dist,通配符被解释为匹配的文件列表

在 slop 中也是相同的情形,为什么会这样,求解 我的需要是把参数包括通配符原封不动传进去

试试 \*.\* 我猜测的

进一步追踪发现是数据装入 ARGV 数组时就自动解释了

p ARGV[0]
p ARGV[1]
p "--"
ARGV.each do |f|
  p f
end
ruby slop.rb *.*
"slop.rb"
"t2.rb"
"--"
"slop.rb"
"t2.rb"
"t.rb"

#1 楼 @huacnlee 转义符是可以用的,但是在使用中这么操作太别扭了...

发现了这篇文章:《Ruby 语言的龌龊之处 - ARGV 自动展开》 http://www.2maomao.com/blog/ruby-rubbish-dirts-argv/ 还是不知道怎么解决..

这个和 Ruby 无关,转义也行,引号引起来也行

#5 楼 @lululau 嗯,没招了,shell 的缘故,貌似无解。只能用引号引起来

我还没有看你代码,不过你对这个问题的描述,跟 Ruby 有嘛关系?

不知道楼主有没有用过 linux 下的 find 命令?

find . -name *.exe, 你觉得我的代码有没有问题?

  1. linux 系的平台下,shell 会进行通配符的展开,和 ruby 没关系。

  2. windows 下,cmd 并不会进行通配符的展开,ruby 为了保持和 linux 的行为一致,做了 glob 处理, 参见源码 (ruby.c):

    void
    ruby_sysinit(int *argc, char ***argv)
    {
    #if defined(_WIN32)
    void rb_w32_sysinit(int *argc, char ***argv);
    rb_w32_sysinit(argc, argv);
    #endif
    ...
    }
    

    其中的 rb_w32_sysinit(argc, argv) 会调用 rb_w32_cmdvector(GetCommandLine(), argv);进行参数的 glob 处理。

且 ruby 没有提供什么选项,也无法提供,因为 linux 的 shell 缘故。

确实没招了,只能转义。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号