Pass variables to Ruby script via command line
Something like this:
ARGV.each do|a|
puts "Argument: #{a}"
end
then
$ ./test.rb "test1 test2"
or
v1 = ARGV[0]
v2 = ARGV[1]
puts v1 #prints test1
puts v2 #prints test2
Pass variable from shell script into inline ruby command?
Your program does not work because the parameter expansion in the command line does not happen in the strings enclosed in apostrophes.
The Ruby code you run is exactly puts $foo
and, because its name starts with $
, for the Ruby code $foo
is an uninitialized global variable. The Ruby program outputs an empty line but the newline is trimmed by $()
and the final value stored in the shell variable bar
is an empty string.
If you try ruby -e "puts $foo"
(because the parameters are expanded between double quotes) you'll find out that it also does not produce what you want but, even more, it throws an error. The Ruby code it executes is puts kroe761
and it throws because kroe761
is an unknown local variable or method name.
Building the Ruby program in the command line this way is not the right way to do it (and doing it right it's not as easy as it seems).
I suggest you to pass the value of $foo
as an argument to the script in the command line and use the global variable ARGV
in the Ruby code to retrieve it.
foo=kroe761
bar=$(ruby -e 'puts ARGV[0]' "$foo")
echo "My name is $bar"
It is very important to put $foo
between quotes, otherwise, if it contains spaces, it is not passed to ruby
as one argument but the shell splits it by spaces into multiple arguments.
Check it online.
Parse command line arguments in a Ruby script
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.
How to pass parameters to ruby command line script
Like many other Unix utilities, ruby
recognizes -
as a special filename for STDIN:
$ echo "p ARGV" | ruby - foo bar
["foo", "bar"]
or:
$ ruby - foo bar << EE
> p ARGV
> EE
["foo", "bar"]
or: (pressing controlD to end the input)
$ ruby - foo bar
p ARGV
["foo", "bar"]
Run ruby script in terminal with parameters
Save it to a file like this:
def add(*numbers)
numbers.inject(0) { |sum, number| sum + number }
end
result = add(*ARGV.map(&:to_i))
puts result
Then run it like ruby add_method.rb 4 6
.
Related Topics
How to Check If a Value Exists in an Array in Ruby
How to Call Methods Dynamically Based on Their Name
How to Track System-Specific Config Files in a Repo/Project
Best Way to Require All Files from a Directory in Ruby
How to Determine If One Array Contains All Elements of Another Array
Best Explanation of Ruby Blocks
Suppress Ruby Warnings When Running Specs
To_D to Always Return 2 Decimals Places in Ruby
How to Use the Conditional Operator (? :) in Ruby
Ruby Block and Unparenthesized Arguments
Ruby Array Access 2 Consecutive(Chained) Elements At a Time
Ruby: What Does 'Require: False' in Gemfile Mean
In Ruby on Rails, to Extend the String Class, Where Should the Code Be Put In