Parse command line arguments in a Ruby script

ruby argv
ruby optparse
ruby command line arguments
ruby optionparser positional arguments
parse command line arguments c
ruby command line arguments gem
ruby args
ruby optparse example

I want to call a Ruby script from the command line, and pass in parameters that are key/value pairs.

Command line call:

$ ruby my_script.rb --first_name=donald --last_name=knuth

my_script.rb:

puts args.first_name + args.last_name

What is the standard Ruby way to do this? In other languages I usually have to use an option parser. In Ruby I saw we have ARGF.read, but that does not seem to work key/value pairs like in this example.

OptionParser looks promising, but I can't tell if it actually supports this case.

Based on the answer by @MartinCortez here's a short one-off that makes a hash of key/value pairs, where the values must be joined with an = sign. It also supports flag arguments without values:

args = Hash[ ARGV.join(' ').scan(/--?([^=\s]+)(?:=(\S+))?/) ]

…or alternatively…

args = Hash[ ARGV.flat_map{|s| s.scan(/--?([^=\s]+)(?:=(\S+))?/) } ]

Called with -x=foo -h --jim=jam it returns {"x"=>"foo", "h"=>nil, "jim"=>"jam"} so you can do things like:

puts args['jim'] if args.key?('h')
#=> jam

While there are multiple libraries to handle this—including GetoptLong included with Ruby—I personally prefer to roll my own. Here's the pattern I use, which makes it reasonably generic, not tied to a specific usage format, and flexible enough to allow intermixed flags, options, and required arguments in various orders:

USAGE = <<ENDUSAGE
Usage:
   docubot [-h] [-v] [create [-s shell] [-f]] directory [-w writer] [-o output_file] [-n] [-l log_file]
ENDUSAGE

HELP = <<ENDHELP
   -h, --help       Show this help.
   -v, --version    Show the version number (#{DocuBot::VERSION}).
   create           Create a starter directory filled with example files;
                    also copies the template for easy modification, if desired.
   -s, --shell      The shell to copy from.
                    Available shells: #{DocuBot::SHELLS.join(', ')}
   -f, --force      Force create over an existing directory,
                    deleting any existing files.
   -w, --writer     The output type to create [Defaults to 'chm']
                    Available writers: #{DocuBot::Writer::INSTALLED_WRITERS.join(', ')}
   -o, --output     The file or folder (depending on the writer) to create.
                    [Default value depends on the writer chosen.]
   -n, --nopreview  Disable automatic preview of .chm.
   -l, --logfile    Specify the filename to log to.

ENDHELP

ARGS = { :shell=>'default', :writer=>'chm' } # Setting default values
UNFLAGGED_ARGS = [ :directory ]              # Bare arguments (no flag)
next_arg = UNFLAGGED_ARGS.first
ARGV.each do |arg|
  case arg
    when '-h','--help'      then ARGS[:help]      = true
    when 'create'           then ARGS[:create]    = true
    when '-f','--force'     then ARGS[:force]     = true
    when '-n','--nopreview' then ARGS[:nopreview] = true
    when '-v','--version'   then ARGS[:version]   = true
    when '-s','--shell'     then next_arg = :shell
    when '-w','--writer'    then next_arg = :writer
    when '-o','--output'    then next_arg = :output
    when '-l','--logfile'   then next_arg = :logfile
    else
      if next_arg
        ARGS[next_arg] = arg
        UNFLAGGED_ARGS.delete( next_arg )
      end
      next_arg = UNFLAGGED_ARGS.first
  end
end

puts "DocuBot v#{DocuBot::VERSION}" if ARGS[:version]

if ARGS[:help] or !ARGS[:directory]
  puts USAGE unless ARGS[:version]
  puts HELP if ARGS[:help]
  exit
end

if ARGS[:logfile]
  $stdout.reopen( ARGS[:logfile], "w" )
  $stdout.sync = true
  $stderr.reopen( $stdout )
end

# etc.

Class: OptionParser (Ruby 2.4.2), When you run a script written in Ruby you can put all kinds of values on the command line after the name of the script: For example:. On the command-line, any text following the name of the script is considered a command-line argument. Separated by spaces, each word or string will be passed as a separate argument to the Ruby program. The following example shows the proper syntax to use to launch the test.rbRuby script from a command-line with the arguments test1and test2.

ARGV, That's exactly what command line arguments do. Each time we run our Ruby program we can feed in different command line arguments, and get different results. OptionParser is DRY. You only have to write the command-line switch, its arguments, the code to run when it's encountered, and the command-line switch description once in your script. OptionParser will automatically generate help screens for you from this description, as well as infer everything about the argument from its description.

I personally use Docopt. This is much more clear, maintainable and easy to read.

Have a look at the Ruby implementation's documentation for examples. The usage is really straightforward.

gem install docopt

Ruby code:

doc = <<DOCOPT
My program who says hello

Usage:
  #{__FILE__} --first_name=<first_name> --last_name=<last_name>
DOCOPT

begin
  args = Docopt::docopt(doc)
rescue Docopt::Exit => e
  puts e.message
  exit
end

print "Hello #{args['--first_name']} #{args['--last_name']}"

Then calling:

$ ./says_hello.rb --first_name=Homer --last_name=Simpsons
Hello Homer Simpsons

And without arguments:

$ ./says_hello.rb
Usage:
  says_hello.rb --first_name=<first_name> --last_name=<last_name>

Ruby: Command Line Arguments with ARGV, Use command-line arguments to pass parameters to your Ruby scripts Ruby script arguments are passed to the Ruby program by the shell,  To read command line args in a Ruby script, use the special Ruby array ARGV to get the information you need. Here are a few examples. 1) Getting the number of command line args To get the number of command line arguments passed in to your Ruby script, check ARGV.length, like this:

A bit of standard Ruby Regexp in myscript.rb:

args = {}

ARGV.each do |arg|
  match = /--(?<key>.*?)=(?<value>.*)/.match(arg)
  args[match[:key]] = match[:value] # e.g. args['first_name'] = 'donald'
end

puts args['first_name'] + ' ' + args['last_name']

And on the command line:

$ ruby script.rb --first_name=donald --last_name=knuth

Produces:

$ donald knuth

Parse command-line arguments, OptionParser is a class that eases the parsing and the interpretation of command​-line options. This class provides a bunch of methods to  If you want to emulate a Unix command line application, this can do it all. Ara T. Howard's Main is a nifty gem for creating command-line scripts. It goes beyond parsing arguments and creates automatic usage and help prompts, all with a nice DSL for specifying the command line options. 2014 Update. A couple new gems have risen to popularity:

An improved version that handles arguments that are not options, arguments with a parameter, and -a as well as --a.

def parse(args)
  parsed = {}

  args.each do |arg|
    match = /^-?-(?<key>.*?)(=(?<value>.*)|)$/.match(arg)
    if match
      parsed[match[:key].to_sym] = match[:value]
    else
      parsed[:text] = "#{parsed[:text]} #{arg}".strip
    end
  end

  parsed
end

Quick Guide to Command-Line Arguments in Ruby, The following example is a complete Ruby program. You can def self.parse(​args) # The options specified on the command line will be collected in *options*. Ruby maintains an array called ARGVwith the values passed on the command line. ARGVis going to be the first value after the name of the script. We can iterate over the elements either directly with a forloop:

Program Arguments in Ruby II: OptionParser - rubycademy, Learn how to parse command line options in your Ruby scripts with the you can then use the OptionParser#parse! method to parse command line arguments​  Using command line arguments adds a new tool to your Ruby toolbelt, which you can use to get user input into your program if you choose. Using Command Line Arguments. Ruby captures command line arguments with a special array named ARGV. When written inside your Ruby program, ARGV will take take a command line command that looks like this: ruby testing_argv.rb these are elements in the argv array

class OptionParser - Documentation for Ruby 2.1.0, Problem. You want to make your Ruby script take command-line arguments, the way most Unix utilities and scripts do. Solution. If you want to treat your  I use a regular ruby argument in the rake file: DB = ARGV[1] then I stub out the rake tasks at the bottom of the file (since rake will look for a task based on that argument name). task :database_name1 task :database_name2 command line: rake mytask db_name this feels cleaner to me than the var=foo ENV var and the task args[blah, blah2] solutions.

HOWTO parse command line options with Ruby OptionParser , In Node.js, as in C and many related environments, all command-line arguments received by the shell are given to the process in an array called argv (short for 'argument values'). Node.js exposes this array for every running process in the form of process.argv - let's take a look at an example. Make a file called argv.js and add this line:

Comments
  • ruby-toolbox.com/categories/CLI_Option_Parsers
  • If I'm not mistaken, Highline seems like helper functions to ask users for input. So I would use Highline to have my console say First Name: and await their input. Is there a particular function I should be looking at in it?
  • There are many gems you can choose from; that website categorizes the libraries and sorts them by popularity. I even wrote my own gem, called acclaim, and it does support the --option=value syntax. I haven't had the time to maintain my free software projects, though. You should pick a better-supported library.
  • Here's a good tutorial on the options parser: dreamsyssoft.com/ruby-scripting-tutorial/…
  • This is nice, but if you're also using the built-in ARGF to read streams via filenames/stdin you need to make sure to consume the arguments from ARGV before using ARGF.read or you will end up with "No such file or directory" errors.
  • How is this not the top answer?
  • I dunno. As they say, "Different strokes for different folks."
  • This is the only sane answer for using options in Ruby. The options are generated and parsed from your help message! Awesome.
  • That's pretty nice! The requirement to use = to disambiguate between -f foo and -x -y bar is a bit of a non-starter for real-world usage for me, but it's a nice quick hack.
  • True. I was just following his format above. Based on the question, I'm not sure if he cares about the disambiguation.
  • That looked awesome but how would you define s? ARGV.join.to_s?
  • I can't see it anymore (your comment)
  • Yes, I deleted my comment, because it was, as you pointed out, wrong. :) It's in my answer, now. Deleting other comments for clean up.