Really Cheap Command-Line Option Parsing in Ruby

前端 未结 20 1128
野的像风
野的像风 2020-11-30 16:57

EDIT: Please, please, please read the two requirements listed at the bottom of this post before replying. People keep posting their new gems and li

20条回答
  •  被撕碎了的回忆
    2020-11-30 17:13

    Here's the code snippet I use at the top of most of my scripts:

    arghash = Hash.new.tap { |h| # Parse ARGV into a hash
        i = -1                      
        ARGV.map{  |s| /(-[a-zA-Z_-])?([^=]+)?(=)?(.+)?/m.match(s).to_a }
         .each{ |(_,a,b,c,d)| h[ a ? "#{a}#{b}#{c}" : (i+=1) ] =
                                 (a ? (c ? "#{d}" : true) : "#{b}#{c}#{d}") 
              }
        [[:argc,Proc.new  {|| h.count{|(k,_)| !k.is_a?(String)}}],
         [:switches, Proc.new {|| h.keys.select{|k| k[0] == '-' }}]
        ].each{|(n,p)| h.define_singleton_method(n,&p) }
    }
    

    I also hate to require additional files in my quick-and-dirty scripts. My solution is very nearly what you're asking for. I paste a 10 line snippet of code at the top of any of my scripts that parses the command line and sticks positional args and switches into a Hash object (usually assigned to a object that I've named arghash in the examples below).

    Here's an example command line you might want to parse...

    ./myexampleprog.rb -s -x=15 --longswitch arg1 --longswitch2=val1 arg2

    Which would become a Hash like this.

     { 
       '-s' => true, 
       '-x=' => '15', 
       '--longswitch' => true, 
       '--longswitch2=' => 'val1', 
       0 => 'arg1', 
       1 => 'arg2'
     }
    

    In addition to that, two convenience methods are added to the Hash:

    • argc() will return the count of non-switch arguments.
    • switches() will return an array containing the keys for switches that are present

    This is mean to allow some quick and dirty stuff like...

    • Validate I've got the right number of positional arguments regardless of the switches passed in ( arghash.argc == 2 )
    • Access positional arguments by their relative position, regardless of switches appearing before or interspersed with positional arguments ( e.g. arghash[1] always gets the second non-switch argument).
    • Support value-assigned switches in the command line such as "--max=15" which can be accessed by arghash['--max='] which yields a value of '15' given the example command line.
    • Test for the presence or absence of a switch in the command line using a very simple notation such as arghash['-s'] which evaluates to true if it's present and nil if its absent.
    • Test for the presence of a switch or alternatives of switches using set operations like

      puts USAGETEXT if !(%w(-h --help) & arghash.switches()).empty?

    • Identify use of invalid switches using set operations such as

      puts "Invalid switch found!" if !(arghash.switches - %w(-valid1 -valid2)).empty?

    • Specify default values for missing arguments using a simple Hash.merge() such as the below example that fills in a value for -max= if one was not set and adds a 4th positional argument if one was not passed.

      with_defaults = {'-max=' => 20, 3 => 'default.txt'}.merge(arghash)

提交回复
热议问题