what is ARGV in ruby and what does it do?
ARGV is basically an array that contains the elements passed to your script. You may find this StackOverflow question useful.
To test it, try creating .rb (let's say it's "test.rb") file in specific folder and put the following code there:
puts ARGV.inspect
Now, try opening a command line window/terminal and point it to the folder where "test.rb" is. Once you're there, type this in your terminal:
ruby test.rb a 1 b
You should get ["a", "1", "b"]
which is the content of ARGV
.
ARGV in Ruby: The Meaning of a Constant
A constant has to have its value newly assigned at some point. If you take the meaning of constant as something that is never newly assigned its value, then there would be no constant at all. A constant is therefore, a relative notion; you cannot define what a constant is without the relevant domain/scope. A constant remains consistant within that domain, but has its value assigned/changed outside of the scope.
In mathematics, suppose some mathematician used a constant A = 3
at some point in their life solving a certain problem. That does not mean that everyone from that point on using the constant A
would always have to assume its value to be 3
. In mathematics, the domain of a constant can be a single proof, an article, a book, or a convention throughout a subfield, etc.
For a computer program, the domain for a constant is usually the execution lifespan of a program. A constant remains constant relative to the execution of the program. ARGV
has its values set prior to the execution of the Ruby program.
What kind of variable is ARGV in ruby?
ARGV is a constant, but it's an Array. Values in a constant array can be freely changed without any warnings, like any usual array element.
irb(main)> ARGV.class
=> Array
irb(main)> QWERTY = [1, 2, 3, 4]
=> [1, 2, 3, 4]
irb(main)> QWERTY[1] = 5
=> 5
irb(main)> QWERTY
=> [1, 5, 3, 4]
irb(main)> QWERTY << 6
=> [1, 5, 3, 4, 6]
irb(main)> QWERTY = 3
(irb): warning: already initialized constant QWERTY
=> 3
Ruby escape ARGV argument or string as argument to shell command
Use require 'shellwords'
and Shellwords.escape
, which will fix this sort of stuff for you:
http://apidock.com/ruby/Shellwords/shellescape
Use ARGV[] argument vector to pass a regular expression in Ruby
Meditate on this:
I wrote a little script containing:
puts ARGV[0].class
puts ARGV[1].class
and saved it to disk, then ran it using:
ruby ~/Desktop/tests/test.rb foo /abc/
which returned:
String
String
The documentation says:
The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\d' will match a backlash followed by ‘d’, instead of a digit.
That means that the regular expression, though it appears to be a regex, it isn't, it's a string because ARGV
only can return strings because the command-line can only contain strings.
When we pass a string into sub
, Ruby recognizes it's not a regular expression, so it treats it as a literal string. Here's the difference in action:
'foo'.sub('/o/', '') # => "foo"
'foo'.sub(/o/, '') # => "fo"
The first can't find "/o/"
in "foo"
so nothing changes. It can find /o/
though and returns the result after replacing the two "o".
Another way of looking at it is:
'foo'.match('/o/') # => nil
'foo'.match(/o/) # => #<MatchData "o">
where match
finds nothing for the string but can find a hit for /o/
.
And all that leads to what's happening in your code. Because sub
is being passed a string, it's trying to do a literal match for the regex, and won't be able to find it. You need to change the code to:
sub(Regexp.new(ARGV[1]), '')
but that's not all that has to change. Regexp.new(...)
will convert what's passed in into a regular expression, but if you're passing in '/o/'
the resulting regular expression will be:
Regexp.new('/o/') # => /\/o\//
which is probably not what you want:
'foo'.match(/\/o\//) # => nil
Instead you want:
Regexp.new('o') # => /o/
'foo'.match(/o/) # => #<MatchData "o">
So, besides changing your code, you'll need to make sure that what you pass in is a valid expression, minus any leading and trailing /
.
Am unable to combine gets.to_i with ARGV arguments, in Ruby
ARGV
looks like an array, but it doesn't behave exactly like one. You won't have access to the second argument, unless you remove the first one first. Your code works if you rewrite it like this:
a, b, c, d, e, f = (0..5).map { ARGV.shift }
puts "you will first go to point #{a}, then #{b}, then #{f}, finishing off with #{e} and finally #{d}."
print "Give me a number: "
time = gets.to_i
puts "you can start at #{time}"
Related Topics
In Rails - Is There a Rails Method to Convert Newlines to <Br>
Rails: Postgres Permission Denied to Create Database on Rake Db:Create:All
Why Should One Use a Http Server in Front of a Framework Web Server
What's the Difference Between Object and Basicobject in Ruby
Is There a Built-In Binary-Search in Ruby
Problems Installing Ruby on Mountain Lion - Ruby 1.9.3 Wont' Compile
Circular Dependency Detected While Autoloading Constant User
Ruby/Rails: Converting a Date to a Unix Timestamp
How to Have Multiple Versions of Ruby and Rails, and Their Combinations on Windows
How to Get the Current Time as 13-Digit Integer in Ruby
How to Deal with the Conflict Between Activesupport::JSON and the JSON Gem
Why Did Matz Choose to Make Strings Mutable by Default in Ruby
Ruby 'Encode': "\Xc3" from Ascii-8Bit to Utf-8 (Encoding::Undefinedconversionerror)