Ruby, OptionParser and multiple flags

Hello all,

I'm currently writing a small script needed for my lab in which I need to parse a few command line arguments in a UNIX like way.

My code goes something like this:

···

#####
#!/usr/bin/ruby -w

require 'optparse'
require 'ostruct'

opciones = OpenStruct.new
opts = OptionParser.new do |opts|
     opts.on("-u USER", "--uid USER", "UID del usuario.") do |usr|
         opciones.user = usr
     end

     opts.on("-h HOST", "--host HOST", String, "Especifica el servidor. Puede ser IP o DNS.") do |h|
         opciones.host = h
     end

     opts.on("-p PORT", "--port PORT", Integer, "Especifica el puerto del servidor. Debe ser entero.") do |p|
         opciones.port = p
     end
end

begin
     opts.parse!(ARGV)
rescue Exception => e
     puts e, opts
     exit!
end

#####

When I run the script I run into the problem that if I use various flags, and forget to put in the required arguments, some flags are taken as arguments. I've read that if I use the coding I've used all three flags, the argument should be obligatory.

To better explain, I'll give some examples:

-----
./script.rb -h
missing argument: -h
-----
Works fine.

-----
./script.rb -p
missing argument: -p
-----
Works fine.

-----
./script.rb -h -p -----
The script accepts -p as the argument for -h, which shouldn't happen as -p is actually a flag.

I'm not sure what the problem is so I need help.

I'm running on a Debian Etch Box i686 with a Ruby 1.8.5 version.

Any help would be greatly appreciated. Thank you all.

--
Jairo E. Lopez
Laboratorio Docente de Computacion
Universidad Simon Bolivar

you've told the option parser that -h accepts an argument and you've given it one. there is no restriction that arguments must not start with a '-' so, in this case, your code is doing it exactly what you told it to do :wink:

-a

···

On May 24, 2007, at 10:13 AM, LDC - Jairo Eduardo Lopez wrote:

Hello all,

I'm currently writing a small script needed for my lab in which I need to parse a few command line arguments in a UNIX like way.

My code goes something like this:

#####
#!/usr/bin/ruby -w

require 'optparse'
require 'ostruct'

opciones = OpenStruct.new
opts = OptionParser.new do |opts|
    opts.on("-u USER", "--uid USER", "UID del usuario.") do |usr|
        opciones.user = usr
    end

    opts.on("-h HOST", "--host HOST", String, "Especifica el servidor. Puede ser IP o DNS.") do |h|

opciones.host = h
    end

    opts.on("-p PORT", "--port PORT", Integer, "Especifica el puerto del servidor. Debe ser entero.") do |p|
        opciones.port = p
    end
end

begin
    opts.parse!(ARGV)
rescue Exception => e
    puts e, opts
    exit!
end

#####

When I run the script I run into the problem that if I use various flags, and forget to put in the required arguments, some flags are taken as arguments. I've read that if I use the coding I've used all three flags, the argument should be obligatory.

To better explain, I'll give some examples:

-----
./script.rb -h
missing argument: -h
-----
Works fine.

-----
./script.rb -p
missing argument: -p
-----
Works fine.

-----
./script.rb -h -p -----
The script accepts -p as the argument for -h, which shouldn't happen as -p is actually a flag.

I'm not sure what the problem is so I need help.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Hi,

At Fri, 25 May 2007 01:13:54 +0900,
LDC - Jairo Eduardo Lopez wrote in [ruby-talk:252822]:

-----
./script.rb -h -p
-----
The script accepts -p as the argument for -h, which shouldn't happen as -p
is actually a flag.

If -h can omit the argument,

     opts.on("-h [HOST]", "--host", String, "Especifica el servidor.",
             "Puede ser IP o DNS.") do |h|
         opciones.host = h
     end

Else, if it must not start with "-", you can restrict it with a
Regexp:

     opts.on("-h HOST", "--host", /[^-].*/, "Especifica el servidor.",
             "Puede ser IP o DNS.") do |h|
         opciones.host = h
     end

/(?!-).+/ results same as above.

···

--
Nobu Nakada

Fair enough. I thought that OptionParser looked out for that sort of thing. Is there anyone who can point me in a direction so that I can try and avoid that sort of confusion between arguments?

···

On Fri, 25 May 2007, ara.t.howard wrote:

On May 24, 2007, at 10:13 AM, LDC - Jairo Eduardo Lopez wrote:

Hello all,

I'm currently writing a small script needed for my lab in which I need to parse a few command line arguments in a UNIX like way.

My code goes something like this:

#####
#!/usr/bin/ruby -w

require 'optparse'
require 'ostruct'

opciones = OpenStruct.new
opts = OptionParser.new do |opts|
   opts.on("-u USER", "--uid USER", "UID del usuario.") do |usr|
       opciones.user = usr
   end

   opts.on("-h HOST", "--host HOST", String, "Especifica el servidor. Puede ser IP o DNS.") do |h|

opciones.host = h
   end

   opts.on("-p PORT", "--port PORT", Integer, "Especifica el puerto del servidor. Debe ser entero.") do |p|
       opciones.port = p
   end
end

begin
   opts.parse!(ARGV)
rescue Exception => e
   puts e, opts
   exit!
end

#####

When I run the script I run into the problem that if I use various flags, and forget to put in the required arguments, some flags are taken as arguments. I've read that if I use the coding I've used all three flags, the argument should be obligatory.

To better explain, I'll give some examples:

-----
./script.rb -h
missing argument: -h
-----
Works fine.

-----
./script.rb -p
missing argument: -p
-----
Works fine.

-----
./script.rb -h -p -----
The script accepts -p as the argument for -h, which shouldn't happen as -p is actually a flag.

I'm not sure what the problem is so I need help.

you've told the option parser that -h accepts an argument and you've given it one. there is no restriction that arguments must not start with a '-' so, in this case, your code is doing it exactly what you told it to do :wink:

-a
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

--
Jairo E. Lopez
Laboratorio Docente de Computacion
Universidad Simon Bolivar

Well, if you specify type of parameters (for example an int) then maybe OptionParser will do it for you (because "-foo" does not translate well to an int). For string arguments you can easily check yourself, like

raise ArgumentError, "No proper option value" if /^-/ =~ value

There is no way to automate that via OptionParser because it cannot know what values you want it to accept. I am not sure whether you can actually provide a regexp that OptionParser will test your argument against - if that feature is there you could easily implement this safety check.

Kind regards

  robert

···

On 25.05.2007 00:46, LDC - Jairo Eduardo Lopez wrote:

On Fri, 25 May 2007, ara.t.howard wrote:

On May 24, 2007, at 10:13 AM, LDC - Jairo Eduardo Lopez wrote:

Hello all,

I'm currently writing a small script needed for my lab in which I need to parse a few command line arguments in a UNIX like way.

My code goes something like this:

#####
#!/usr/bin/ruby -w

require 'optparse'
require 'ostruct'

opciones = OpenStruct.new
opts = OptionParser.new do |opts|
   opts.on("-u USER", "--uid USER", "UID del usuario.") do |usr|
       opciones.user = usr
   end

   opts.on("-h HOST", "--host HOST", String, "Especifica el servidor. Puede ser IP o DNS.") do |h|

opciones.host = h
   end

   opts.on("-p PORT", "--port PORT", Integer, "Especifica el puerto del servidor. Debe ser entero.") do |p|
       opciones.port = p
   end
end

begin
   opts.parse!(ARGV)
rescue Exception => e
   puts e, opts
   exit!
end

#####

When I run the script I run into the problem that if I use various flags, and forget to put in the required arguments, some flags are taken as arguments. I've read that if I use the coding I've used all three flags, the argument should be obligatory.

To better explain, I'll give some examples:

-----
./script.rb -h
missing argument: -h
-----
Works fine.

-----
./script.rb -p
missing argument: -p
-----
Works fine.

-----
./script.rb -h -p -----
The script accepts -p as the argument for -h, which shouldn't happen as -p is actually a flag.

I'm not sure what the problem is so I need help.

you've told the option parser that -h accepts an argument and you've given it one. there is no restriction that arguments must not start with a '-' so, in this case, your code is doing it exactly what you told it to do :wink:

-a
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Fair enough. I thought that OptionParser looked out for that sort of thing. Is there anyone who can point me in a direction so that I can try and avoid that sort of confusion between arguments?