gets.chomp without moving to a new line
You can do this by using the (very poorly documented) getch
:
require 'io/console'
require 'io/wait'
loop do
chars = STDIN.getch
chars << STDIN.getch while STDIN.ready? # Process multi-char paste
break if ["\r", "\n", "\r\n"].include?(chars)
STDOUT.print chars
end
References:
- http://ruby-doc.org/stdlib-2.1.0/libdoc/io/console/rdoc/IO.html#method-i-getch
- http://ruby-doc.org/stdlib-2.1.0/libdoc/io/wait/rdoc/IO.html#method-i-ready-3F
Related follow-up question:
enter & IOError: byte oriented read for character buffered IO
How to use gets and gets.chomp in Ruby
gets
lets the user input a line and returns it as a value to your program. This value includes the trailing line break. If you then call chomp
on that value, this line break is cut off. So no, what you have there is incorrect, it should rather be:
gets
gets a line of text, including a line break at the end.- This is the user input
gets
returns that line of text as a string value.- Calling
chomp
on that value removes the line break
The fact that you see the line of text on the screen is only because you entered it there in the first place. gets
does not magically suppress output of things you entered.
In Ruby, how can I print my next prompt on the same line after user input?
The reason you get a new line even after chomp
is because in the terminal you've already entered the carriage return key which displays the new line.
What you want can be done like this:
require "io/console"
print "Move FROM which tower? (1 / 2 / 3) "
x = STDIN.getch.to_i
print x
print "...TO which tower? (1 / 2 / 3) "
y = STDIN.getch.to_i
print "#{y}\n"
print "Result: (#{x}, #{y})"
Note this will give an output of this:
$ ruby tower.rb
Move FROM which tower? (1 / 2 / 3) 1...TO which tower? (1 / 2 / 3) 2
Result: (1, 2)
Note this only gets one character from STDIN
.
Perl's Chomp: Chomp is removing the whole word instead of the newline
The reason you see only a string of 1
s is that you are printing the value of $val
which is the value returned from chomp
. chomp
doesn't return the trimmed string, it modifies its parameter in-place and returns the number of characters removed from the end. Since it always removes exactly one "\n"
character you get a 1
output for each element of the array.
You really should use warnings
instead of the -w
command-line option, and there is no reason here to read the entire file into an array. But well done on using a lexical filehandle with the three-parameter form of open
.
Here is a quick refactoring of your program that will do what you want.
#!/usr/bin/perl
use strict;
use warnings;
my $file = 'test.csv';
open my $FH, '<', $file or die qq(Unable to open "$file": $!);
while (<$FH>) {
chomp;
my @row = split /,/;
print $row[1], "\n";
}
gets.chomp three times in a row to exit
Have a look at this, I've made some changes though. But should give you the expected output.
bye_count = 0
while true
speak = gets.chomp
if speak == 'BYE'
bye_count +=1
bye_count == 3 ? break : next
end
bye_count = 0 # Resets count
if speak == speak.upcase
puts 'NO, NOT SINCE ' + (1930 + rand(20)).to_s + '!'
else
puts 'HUH?! SPEAK UP, SONNY!'
end
end
How to pass text from gets.chomp to a file
Making the assumption that there will only ever be one resources :posts
in your routes file, a simple example could be done like:
require 'active_support/core_ext/string/inflections' # for `pluralize`
get = gets.chomp
lines = File.read("config/routes.rb").split(/\n/)
# find the line of the file we want to insert after. This assumes
# there will only be a single `resources :posts` in your routes.
index = lines.index { |line| line.strip == 'resources :posts' }
# duplicate the existing line and replace 'posts' with the pluralized form
# of whatever the user input to gets, we do it this way to keep indentation
new_line = lines[index].gsub(/posts/, get.pluralize)
# insert the new line on the line after the `resources :posts` and then write
# the entire thing back out to 'config/routes.rb'
lines.insert(index + 1, new_line)
File.open("config/routes.rb", "w") { |f| f.write(lines.join("\n")) }
Depending on what you're trying to do, though, you may find it useful to look into Rails Generators.
before
Rails.application.routes.draw do
resources :users do
resources :posts
end
end
execute
$ echo category | ruby example.rb
after
Rails.application.routes.draw do
resources :users do
resources :posts
resources :categories
end
end
Passing an gets.chomp as an argument
Because IO#gets
reads next line from readable I/O stream(in this case it's a file) and returns a String
object when reading successfully and not reached end of the file. And, chomp
removes carriage return characters from String
object.
So when you have a file with content such as:
This is file content.
This file has multiple lines.
The code will print:
1, This is file content.
2, This file has multiple lines.
In the second case, you're passing file object itself and not reading it. Hence you see those objects in output.
Related Topics
Unable to Delete File from Amazon S3 Using Ruby Script
Nanoc Changing the Base Path When Deploying Page in Github
In Rspec, Using Let Variable Inside Before :All Block
What Is the Advantage of Creating an Enumerable Object Using To_Enum in Ruby
What Regex How to Use to Get the Domain Name from a Url in Ruby
In Ruby How to Tell If a String Input Is in Uppercase or Lowercase
Cannot Install Any Ruby Gems on MAC Os - Ssl_Connect Error
Ruby: How Does Constant-Lookup Work in Instance_Eval/Class_Eval
Scraping a Site That Requires Login Username and Password on Two Separate Pages
Writing Ruby Console Output to Text File
How to Test Whether a String Would Match a Glob in Ruby
Flash Message with HTML_Safe from the Controller in Rails 4 (Safe Version)
Ruby Equivalent of C#'s 'Yield' Keyword, Or, Creating Sequences Without Preallocating Memory
Problem Installing Ruby 1.9.2 on MAC Os Lion
Bundler Could Not Find Compatible Versions for Gem "Bundler": in Gemfile: