Passing an array as a command argument

I am trying to pass an array to a ruby ​​script from the command line and am running into some problem.

Here's the problem:

require 'pp'

def foo(arr1, var, arr2, var2)
  puts arr1.class
  pp arr1
  pp arr1[0]
  puts arr2.class
  pp arr2
  pp arr2[0]
end

foo [1, 2], 3, [5, 6], 8

      

Here's the result:

Array
[1, 2]
1
Array
[5, 6]
5

      

Things are good. Now I modify my script to accept an argument from the command line:

require 'pp'

def foo(arr1,var)
  puts arr1.class
  pp arr1
  pp arr1[0]
end
foo ARGV[0],3

      

Here's the result:

jruby test.rb [1, 2], 3, [5, 6], 8
String
"[1,"
91
String
"2],"
50

      

As you can see, the array is passed as a string, and arr [0] basically prints the ascii value.

So the question is how to pass the array from the command line, hopefully in one line. Also I believe this question is related to all shell calls than just ruby?

I am using bash shell.

Update: Just updated the question to indicate that there could be multiple arrays at different positions.

+3


source to share


3 answers


You can use eval, although you can open a security hole:

require 'pp'

def foo(arr1, var, arr2, var2)
  puts arr1.class
  pp arr1
  pp arr1[0]
  puts arr2.class
  pp arr2
  pp arr2[0]
end

eval("foo " + ARGV.join(" "))

      

Result



Array
[1, 2]
1
Array
[5, 6]
5

      

Hope it helps

0


source


Here's a list of ways to accomplish this. Stay away from based solutions eval

. My favorite (although I don't know ruby, but this is my favorite:



irb(main):001:0> s = "[5,3,46,6,5]"
=> "[5,3,46,6,5]"
irb(main):002:0> a = s.scan( /\d+/ )
=> ["5", "3", "46", "6", "5"]
irb(main):003:0> a.map!{ |s| s.to_i }
=> [5, 3, 46, 6, 5]

      

+2


source


The arguments will always be presented as a string, you need to find a way to turn them into the format you want, in your example an array of values ​​followed by one value. I suggest using trollop as a way to get away from arguments hard. It can take multivalued arguments like

require 'trollop'

opts = Trollop.options do 
    opt :array, 'an array', type: :ints
    opt :val, 'a value', type: :int
end

puts "array: #{opts[:array].inspect}"
puts "val: #{opts[:val].inspect}"

      

Then you can do:

$ ruby test.rb -a 1 2 -v 3
array: [1, 2]
val: 3

      

And it's also nice:

$ ruby test.rb --help
Options:
 --array, -a <i+>:   an array
 --val, -v <i>:   a value
 --help, -h:   Show this message

      

+2


source







All Articles