Forum: Ruby String to array as command line

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
unknown (Guest)
on 2006-03-26 20:04
(Received via mailing list)
Hello,

I can't find a function that takes a string as an input, parses it and
returns an array in the exactly same way as command line is parsed into
ARGV array variable.
Could you give me a hint?

Thanks in advance
Lubos
Daniel H. (Guest)
on 2006-03-26 20:13
(Received via mailing list)
On Mar 26, 2006, at 6:03 PM, removed_email_address@domain.invalid wrote:

> Hello,
>
> I can't find a function that takes a string as an input, parses it and
> returns an array in the exactly same way as command line is parsed
> into
> ARGV array variable.
> Could you give me a hint?
>
> Thanks in advance
> Lubos

require 'shellwords'
args = Shellwords.shellwords('foo\ bar "another shellword"') # =>
["foo bar", "another shellword"]

-- Daniel
unknown (Guest)
on 2006-03-26 20:24
(Received via mailing list)
On Mon, 27 Mar 2006, Daniel H. wrote:

>> Thanks in advance
>> Lubos
>
> require 'shellwords'
> args = Shellwords.shellwords('foo\ bar "another shellword"') # => ["foo bar",
> "another shellword"]
>
> -- Daniel

but that will only be similar to sh-like shells.  i think a portable way
to do
it would be

   harp:~ > cat a.rb
   def command_line string
     Marshal::load(IO::popen("ruby -r yaml -e' print Marshal::dump(ARGV)
' #{ string }"){|io| io.read})
   end

   p command_line(' foo bar foobar ')
   p command_line(' "foo bar" "foobar" ')
   p command_line(' foo $bar ')
   p command_line(' foo "$bar" ')
   p command_line(" foo '$bar' ")


   harp:~ > ruby a.rb
   ["foo", "bar", "foobar"]
   ["foo bar", "foobar"]
   ["foo"]
   ["foo", ""]
   ["foo", "$bar"]

this may be overkill but it should work regardless of the shell in use.

-a
unknown (Guest)
on 2006-03-26 20:44
(Received via mailing list)
Thank you..
The behavior is not  exactly the same (at least on Win) but I think I
can live with it ;-)...

Lubos

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
ARGV.each {|ch|
 puts ch
}
puts '********'
args = Shellwords.shellwords('-v "\"\\"')
args.each {|ch|
  puts ch
}
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
>>prog.rb -v "\"\\"  "foo\ bar" "another shellword"
-v
"\
********
c:/ruby/lib/ruby/1.8/shellwords.rb:39:in `shellwords': Unmatched double
quote:
 (ArgumentError)
        from c:/ruby/lib/ruby/1.8/shellwords.rb:35:in `loop'
        from c:/ruby/lib/ruby/1.8/shellwords.rb:35:in `shellwords'
unknown (Guest)
on 2006-03-26 20:54
(Received via mailing list)
The following error raised:

test.rb:503:in `load': incompatible marshal file format (can't
be read) (TypeError) format version 4.8 required; 114.117 given

I use:

>ruby --version
ruby 1.8.2 (2004-12-25) [i386-mswin32]

Could this be a problem?

L.
lubos (Guest)
on 2006-03-26 21:44
(Received via mailing list)
I have found the problem:
the correct version is :

def command_line string
     Marshal::load(IO::popen("ruby -r yaml -e' print
Marshal::dump(ARGV) ' -- #{ string }"){|io| io.read})
   end

the problem was that I put the "-v" parameter in the string and it was
used by ruby itself and thus destroyed the marshaled stream...
the added  "--" parametr avoid this behavior.

Thanks, this is exactly what I was looking for..
unknown (Guest)
on 2006-03-26 21:56
(Received via mailing list)
On Mon, 27 Mar 2006, lubos wrote:

> the added  "--" parametr avoid this behavior.
>
> Thanks, this is exactly what I was looking for..

ah - yes - good catch.  i guess it goes without saying that this is
somewhat
expensive... but it should be portable.  about the only other thing
would be
to dynamically determine which ruby to run instead of relying on the
PATH
setting

   require "yaml"
   require "rbconfig"

   def command_line string
     cline = lambda{|ruby| Marshal::load(IO::popen("#{ ruby } -r yaml
-e' print Marshal::dump(ARGV) ' -- #{ string }"){|io| io.read}) }
     c = ::Config::CONFIG
     ruby = File::join(c["bindir"], c["ruby_install_name"]) <<
c["EXEEXT"]
     begin
       cline[ruby] # don't depend on PATH
     rescue
       cline["ruby"] # depend on PATH as fallback
     end
   end


regards.

-a
This topic is locked and can not be replied to.