Kane Ho
Kane Ho

Reputation: 119

How can Ruby OptionParser take care of parameter with spaces?

I am trying to define the options for my Ruby script which sending messages from User A to User B for testing purpose. However I couldn't get it work when some of the option have spaces in the value. For example:

    OptionParser.new do |opts|
      opts.on("-p", "--params a=A,b=B,c=C", Array, "Parameters to compose the message") do |params|
        options.params = params.map { |p| p.split("=") }
      end
    end

But when I try to specify thing like -p SENDER=foo,RECIPIENT=bar,BODY=foo bar it just gave me back ["SENDER" => "foo", "RECIPIENT" => "bar", "BODY" => "foo"].

I have also tried -p SENDER=foo,RECIPIENT=bar,BODY='foo bar' but no luck with it either.

Does OptionParser support this scenario?

Thank you!

Upvotes: 2

Views: 2640

Answers (1)

the Tin Man
the Tin Man

Reputation: 160631

Use single or double quotes to surround the parameter:

-p 'SENDER=foo,RECIPIENT=bar,BODY=foo bar'

For example:

require 'optparse'

options = {}
OptionParser.new do |opt|
  opt.on('-p', '--params OPTS', Array) { |o| options[:p] = o }
end.parse!

require 'pp'
pp options # =>

Running that at the command-line using:

ruby test.rb --params 'SENDER=foo,RECIPIENT=bar,BODY=foo bar'

Outputs:

{:p=>["SENDER=foo", "RECIPIENT=bar", "BODY=foo bar"]}

This isn't an OptionParser issue, it's how the command-line works when parsing the options and passing them to the script. OptionParse only gets involved once it sees the argument 'SENDER=foo,RECIPIENT=bar,BODY=foo bar' and splits it on the commas into an array and passes that to the opt.on block:

'SENDER=foo,RECIPIENT=bar,BODY=foo bar'.split(',')
# => ["SENDER=foo", "RECIPIENT=bar", "BODY=foo bar"]

It looks like you're trying to split the incoming data into an array of arrays because of:

options.params = params.map { |p| p.split("=") }

I'd recommend considering converting it into a hash instead:

opt.on('-p', '--params OPTS', Array) { |o| options[:p] = Hash[o.map{ |s| s.split('=') }] }

Which results in:

{:p=>{"SENDER"=>"foo", "RECIPIENT"=>"bar", "BODY"=>"foo bar"}}

And makes it easy to get at specific entries passed in:

pp options[:p]['BODY'] # => "foo bar"

Upvotes: 5

Related Questions