In Ruby, why aren't variables not interchangeable within code blocks? - ruby

I have a file called "file1.txt":
Ruby
programming
is fun
In files.rb, which I'm calling from IRB, I have:
File.open('file1.txt', 'r') do |file|
while line = file.gets
puts "** " + line.chomp + " **" #--> why can't I use file.gets.chomp?
end
end
Why isn't line and file.gets interchangeable on line 3? If I switch line with file.gets, the function does not work, and I am a little bit perplexed considering that
line = file.gets
and
file.gets = line
should be interchangeable, but in this case, it is not as it gives me an error. The function works with line.chomp.
I tried getting rid of the while code block, and simply writing
puts file.gets
and it seems to output a line of code from file1.txt, but does not work inside the while statement on line 3.

I'm not really into Ruby, but I think that is because if you use while line = file.gets, the file.gets return a line and read (and copy to buffer) the next one. In the final iteration, where the while is in the last line, the while line = file.gets will return the last line. But in the while, you call again file.gets, so as there are no more lines in file, it returns an error.

This is untested, but your code can be reduced to:
File.foreach('file1.txt') do |line|
puts "** " + line + " **"
end

Related

Could gets be a loop condition?

Wanted to make a loop asking the user for input each time and break the loop as soon as the input is empty.
lines << line while line = gets.chomp
The code above fails to break the loop. Using the irb and putting in nothing showed that the condition doesn't return a nil:
irb(main):001:0> line = gets.chomp
=> ""
Is there a way to get it work?
The problem that in you sample while loop will break when line is null, but gets.chomp will return empty string when empty line is given.
Simplest solution to use loop with explicit break
lines = []
loop do
line = gets.chomp
break if line.empty?
lines << line
end
If you would use ActiveSupport library(included with Rails) you can do one liner with presence method
lines << line while line = gets.chomp.presence

Ruby filtering specific lines from a text file

I'm a newbie! I have a text file that contains lines and lines of text. I want to try to create a code that only allows the lines that have the phrase "larry.bird" show while the others are deleted. This is my current code...
File.open("HM.txt").each do |line|
   puts line
   if line.include? "larry.bird"
      puts "larye.bird " + line
   end
end
File.readlines('HM.txt') do |li|
  puts li if (li['larry.bird'])
end
If you can help me out, that would be awesome!
You're pretty close. You're opening and reading the file correctly; you're just accidentally printing every line before performing the check. The puts line on the second line of your code is ensuring that this occurs.
File.open("HM.txt") do |file|
file.each_line do |line|
if line.include? "larry.bird"
puts "larry.bird " + line
end
end
end
We can also shorten one-line if statements in Ruby, using suffix notation that often makes code more concise.
File.open("HM.txt") do |file|
file.each_line do |line|
puts "larry.bird " + line if line.include? "larry.bird"
end
end
This is equivalent to the first example.

reading text file lines in ruby

I would like to scan each line in a text file, EXCEPT the first line.
I would usually do:
while line = file.gets do
...
...etc
end
but line = file.gets reads EVERY single line starting from the first.
How do I read from the second line onwards?
Why not simply call file.gets once and discard the result:
file.gets
while line = file.gets
# code here
end
I would do it in a simple fashion:
IO.readlines('filename').drop(1).each do |line| # drop the first array element
# do any proc here
end
Do you actually want to avoid reading the first line or avoid doing something with it. If you are OK reading the line but you want to avoid processing it then you can use lineno to ignore the line during processing as follows
f = File.new "/tmp/xx"
while line = f.gets do
puts line unless f.lineno == 1
end

Concatenating strings with variables with Ruby

I am writing a test script that opens a file with a list of URLs without the "www" and "com".
I am trying to read each line and put the line into the URL. I then check to see if it redirects or even exists.
My problem is when I read the line from the file and assign it to a variable. I then do a compare with what's in the URL after loading and what I initially put in there, but it seems to be adding a return after my variable.
Basically it is always saying redirect because it puts "http://www.line\n.com/".
How can I get rid of the "\n"?
counter = 1
file = File.new("Data/activeSites.txt", "r")
while (line = file.gets)
puts "#{counter}: #{line}"
counter = counter + 1
browser.goto("http://www." + line + ".com/")
if browser.url == "http://www." + line + ".com/"
puts "Did not redirect"
else
puts ("Redirected to " + browser.url)
#puts ("http://www." + line + ".com/")
puts "http://www.#{line}.com/"
end
Basically it is always saying redirect because it puts http://www.line and then return .com/
How can I get rid of the return?
Short answer: strip
"text\n ".strip # => "text"
Long answer:
Your code isn't very ruby-like and could be refactored.
# Using File#each_line, the line will not include the newline character
# Adding with_index will add the current line index as a parameter to the block
File.open("Data/activeSites.txt").each_line.with_index do |line, counter|
puts "#{counter + 1}: #{line}"
# You're using this 3 times already, let's make it a variable
url = "http://#{line}.com"
browser.goto(url)
if browser.url == url
puts "Did not redirect"
else
puts ("Redirected to " + browser.url)
puts url
end
end
That's because your lines are terminated by a newline. You need to strip it off:
while (line = file.gets)
line.strip!
puts "#{counter}: #{line}"
# ...
Note that there are better ways of iterating over the lines in a file:
File.foreach("Data/activeSites.txt") do |line|
# ...
end
This is your code after reindenting it to the "Ruby way":
counter = 1
file = File.new("Data/activeSites.txt", "r")
while (line = file.gets)
puts "#{counter}: #{line}"
counter = counter + 1
browser.goto("http://www." + line + ".com/")
if browser.url == "http://www." + line + ".com/"
puts "Did not redirect"
else
puts ("Redirected to " + browser.url)
#puts ("http://www." + line + ".com/")
puts "http://www.#{line}.com/"
end
It's not correct because it's missing a closing end for the while. But, it's also not dealing with file IO correctly.
This is how I'd write it:
File.foreach("Data/activeSites.txt") do |line|
puts "#{ $. }: #{ line }"
browser.goto("http://www.#{ line }.com/")
if browser.url == "http://www.#{ line }.com/"
puts "Did not redirect"
else
puts "Redirected to #{ browser.url }"
puts "http://www.#{ line }.com/"
end
end
File.foreach is a method inherited from IO. If you read the file correctly you don't need to strip or chomp, because Ruby will handle it correctly when IO.foreach reads the line.
Every time IO reads a line it increments the $. global, which is short-hand for $INPUT_LINE_NUMBER. There's no need to keep a counter. Using:
require 'english'
will enable the verbose names. See the English docs for more information.

Ruby console overwrites line when printing out lines in a file

I have started learning Ruby and I have come across an annoying problem. I have imported a text file into my program and I want to iterate over the lines in it and print them out to the screen.
When I do this, the console overwrites the last printed out line and writes the new one on top. Why is this happening and how can I solve it?
Here is my code:
passwords = File.open('C:\Users\Ryan\Desktop\pw.txt', 'r')
lines = passwords.gets
for line in lines
puts line
end
Update:
The loop is acting very strange. I put a sleep statement into it and all it did was sleep once then continue to output the lines. I would have expected it to sleep before outputting each line. Example below:
passwords.each do |line|
sleep 1
puts line.chomp
end
Update 2:
I just created a new text file and typed some random stuff into it for testing and it works fine. Looks like the original file had some bad characters/encoding which messed up the printing to the console.
Do you have an EOL (AKA end-of-line) problem? Try this:
passwords = File.open('C:\Users\Ryan\Desktop\pw.txt', 'r')
lines = passwords.gets
lines.each { |line| puts line.chomp }
passwords.close
The chomp call will strip off any \n, \r, or \r\n line endings, then puts will append the native EOL.
File.open('C:\Users\Ryan\Desktop\pw.txt') do |line|
while not line.eof?
puts line.readline.chomp
end
end
or
File.read("file").each { |line| puts line.chomp }
In the end I found out that the text file was the cause of my problem. I created a new one with the same content and it started working how I intended.

Resources