How can same program in ruby accept input from user as well as command line arguments
gets
will only read from the real $stdin
(ie the user) if there are no command line arguments. Otherwise it'll take those arguments as files to concatenate as a virtual $stdin
.
You can use STDIN.gets
to make sure you're always using the right function.
You can also delete the arguments from ARGV
as you go (or remove them all in one go), your gets
should work correctly.
How can I get user input from command line with this program?
ARGV
is an array. You have to get its first element.
print ARGV # An array
x = ARGV[0]
print x
With ruby filename.rb 123
, ARGV
is ["123"]
and x
is "123"
.
When specifying command-line arguments Ruby no longer waits for input using gets
In addition to STDIN.gets like others have recommended, you can use plain gets
if you call ARGV.clear
beforehand. The regular gets
works as expected if there aren't command like arguments to the script, but if there are, then it will read them. It's not really clear why you're using ./test.rb test.rb
, but the second filename is a command line argument.
More specifically, if regular gets
is called when ARGV is populated, then the result will be the contents of the file.
max@max ~> echo "content" > test.txt
max@max ~> ruby -e "puts ARGV.inspect; puts gets" test.txt
["test.txt"]
content
Accept multiple command-line arguments through ARGV/ARGF
This would be easily done using a command-line arguments parsing library like OptionParser.
require 'optparse'
LOG_LEVELS = ['DEBUG', 'INFO ', 'WARN ', 'ERROR', 'FATAL']
def error_sort(log_file)
LOG_LEVELS.each do |log_level|
File.readlines(log_file).each do |line|
if (line =~ /<#{log_level}>/ .. line =~ /<(?!#{log_level}).+>/) && line !~ /<(?!#{log_level}).+>/
File.open("#{log_level}.txt", "a") << line
end
end
end
end
def read_log(log_file, step)
File.readlines(log_file).each do |line|
if line.match /Recording dut_serial_number/
File.open("step_#{step}", "a") << line
elsif (line =~ /Beginning step ##{step} / .. line =~ /Beginning step #(?!#{step}).+ /) && line !~ /Beginning step #(?!#{step}).+ /
File.open("step_#{step}", "a") << line
else
nil
end
end
end
options = {}
optparse = OptionParser.new do |opts|
opts.on("--sort", "Explain what this option does here.") do
options[:sort] = true
end
opts.on("--step NUM", Integer, "Explain what this option does here.") do |num|
options[:step] = num # num is automatically converted to an Integer
end
end
optparse.parse! # all non-option arguments remain in ARGV
log_file = ARGV[0]
if options[:sort]; error_sort(log_file); end
if options[:step]; read_log(log_file, options[:step]); end
More information on OptionParser:
- http://ruby.about.com/od/advancedruby/a/optionparser2.htm
- http://ruby-doc.org/stdlib-2.1.2/libdoc/optparse/rdoc/OptionParser.html
EDIT:
In order to allow using the same flag twice, e.g. --step 3 --step 5
, we can change the :step
entry in our options
map to be an array of specified numbers, like this:
options = {:step => []}
optparse = OptionParser.new do |opts|
...
opts.on("--step NUM", Integer, "Explain what this option does here.") do |num|
options[:step] << num
end
end
Then change the semantics of what your program does with the :step
argument, which is now an array instead of a single number:
unless options[:step].empty?
options[:step].each {|n| read_log(log_file, n)}
end
All non-option arguments remain in ARGV
, so you can enable multiple file processing easily:
ARGV.each do |log_file|
if options[:sort]
error_sort(log_file)
end
unless options[:step].empty?
options[:step].each {|n| read_log(log_file, n)}
end
end
How to pass text file as an argument in Ruby
On your shell, invoke the ruby
script followed by the name of the .txt
file, like this:
ruby foo.rb test_list.txt
The variable ARGV
will contain references to all the arguments you've passed when invoking the ruby
interpreter. In particular, ARGV[0] = "test_list.txt"
, so you can use this instead of hardcoding the name of the file:
File.open(ARGV[0]).each do |line|
puts line
end
On the other hand, if you want to pass the content of the file to your program, you can go with:
cat test_list.txt | ruby foo.rb
and in the program:
STDIN.each_line do |line|
puts line
end
How do I use the system() command to pass in user input?
You should look into the Open3 library from the Ruby stdlib. It gives you more control over "shelling out".
output, status = Open3.capture2("./script", :stdin_data => "I am STDIN")
Read input from console in Ruby?
Are you talking about gets
?
puts "Enter A"
a = gets.chomp
puts "Enter B"
b = gets.chomp
c = a.to_i + b.to_i
puts c
Something like that?
Update
Kernel.gets
tries to read the params found in ARGV
and only asks to console if not ARGV
found. To force to read from console even if ARGV
is not empty use STDIN.gets
User input to create factorial
You actually seem to be asking for two different things. The first thing you want is an application that does something like this
$ ruby factorial.rb
> Please input a non-negative integer
(GET USER INPUT)
> The factorial of (USER INPUT) is (FACTORAIL OF USER INPUT)
And a command line tool that does something like this
$ fact 10
> 3628800
The first one could look something like this
def fact(n)
(1..n).inject(:*)
end
puts 'Please input a non-negative integer'
a = gets.to_i
puts "The factorial of #{a} is #{fact(a)}"
The second one could look something like this
#!/usr/bin/ruby
puts (1..ARGV[0].to_i).inject(:*)
Changing behavior of gets, when reading from command line, in Ruby
Check the docs:
If
Kernel.gets
sees thatARGV
is set, it uses them as filenames to
feed instead of reading from stdin. So use an expicit:$stdin.gets
Related Topics
Why Doesn't Puts() Print in a Single Line
Reading Parameters on Sinatra Post
How to Pass Value from One Resource to Another Resource in Chef Recipe
Jekyll Liquid - Accessing _Config.Yml Dynamically
Why Are Parenthesis Sometimes Required in Ruby
Ruby/Rails Actionmailer Not Working with Ntlm
Why Capypara + Rspect Tests Still Pass Even Though I Delete Application.Js File
Ruby- Delete a Value from Sorted (Unique) Array at O(Log N) Runtime
Find and Replace Specific Hash and It's Values Within Array
Can Nokogiri Use Single Quotes for Attributes on Saving Xml
Rspec Matcher That Checks Collection to Include Item That Satisfies Lambda
Ruby on Windows7 - Could Not Find Gem
Exclude Some Ids from Result in Rails Activerecord
Regex to Match Mm/Dd/Yyyy Hh:Mm:Ss Am or Pm
Any Ruby Library to Inspect What Are the Arguments That a Certain Methods Take