I am doing exercise 16 at learnrubythehardway.org.
The name of a file is passed as argument to the following script, which asks the user to write three lines to the file:
filename = ARGV.first
puts "Opening the file..."
target = open(filename, 'w+')
puts "Now I am going to ask you for three lines."
print "line 1: "
line1 = $stdin.gets.chomp
print "line 2: "
line2 = $stdin.gets.chomp
print "line 3: "
line3 = $stdin.gets.chomp
puts "I am going to write these to the file."
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
puts "Here is your new file:"
print target.read
puts "And finally we close it"
target.close
Just before closing the file I would like the user be given the opportunity to see the content of the new file, however that part of the code is not processed. Why is that?
You have to rewind the file, if you want to read what you have just written.
target.write(line3)
target.write("\n")
target.rewind
target.read
Bonus content
Use puts, it writes the newline for you.
target.puts(line3)
Related
I have a txt file and I want to extract only the first word of a line which contains the characters 'ath'.
File.open("myfile.txt").readlines.each do |line|
if line =~ /ath/
line.split.first
puts line
$line = line.chomp
puts "Ok"
else
nil
end
end
line.split.first only works if the first word of the line is a match, because when I do the same in irb:
"im here to ask someting easy".split.first
The output is 'im'.
If the first word in a line contains ath at any point
if line =~ /^\S*ath\S*/
I'm very new to the Ruby world so please bear if its a simple query.
For one of my assignments, I'm looking to read the contents of all the text files in a folder (only top level) and redirect the file contents to a single output file in a appended or merged manner.
I'm a expecting a format like below:
Output File
File Name: 1st file name
all its contents
====================================
File Name: 2nd file name
all its contents
====================================
File Name: 3rd file name
all its contents
====================================
....
....
====================================
I managed to write the below script but the output file is empty. Any suggestions please.
File.open('C:\Users\darkop\Desktop\final_output.txt','a') do |final|
#files = Dir.glob("D:\text\*.txt")
for file in #files
text = File.open(file, 'r').read.sub(/#$/?\z/, $/)
text.each_line do |line|
puts "File Name:"#{file}
puts
final << line
puts "=" * 20
end
end
end
Also, is it possible to redirect the output in aforementioned format to a word document instead of a text file ?
Many thanks.
This should work.
The file name was empty because you have puts "File Name:"#{file}. This way #{file} doesn't get interpolated, because it isn't inside the double quotation marks.
Also, you didn't get the contents of the file because you just used puts, instead of puts line, which is what you want.
File.open('C:\Users\darkop\Desktop\final_output.txt','a') do |final|
#files = Dir.glob("D:\text\*.txt")
for file in #files
text = File.open(file, 'r').read.sub(/#$/?\z/, $/)
text.each_line do |line|
puts "File Name: #{file}"
puts
puts line
final << line
puts "=" * 20
end
end
end
-EDIT-
Since you are new to Ruby, it's better to use an each loop, instead of the for .. in loop. Also, just specify the output name with a .doc extension for a Word document.
File.open('C:\Users\darkop\Desktop\final_output.doc','a') do |final|
#files = Dir.glob("D:\text\*.txt")
#files.each do |file|
text = File.open(file, 'r').read.sub(/#$/?\z/, $/)
text.each_line do |line|
puts "File Name: #{file}"
puts
puts line
final << line
puts "=" * 20
end
end
end
I understand how to open and then print the content of the file. I would like to understand how to ask a second question on a new line after the txt file has been printed.
The code below prints the output of the text file, then on the same line, asks "Type the file name again:"
filename = ARGV.first
txt = open(filename)
puts "Here's your file #{filename}:"
print txt.read
print "Type the filename again: "
file_again = $stdin.gets.chomp
txt_again = open(file_again)
print txt_again.read
I would like this question to be printed on a new line after the txt file has been read.
You should use puts and not print.
The difference is that puts add a new line at the end of the output.
filename = ARGV.first
txt = open(filename)
puts "Here's your file #{filename}:"
puts txt.read // Changed Line
print "Type the filename again: "
file_again = $stdin.gets.chomp
txt_again = open(file_again)
puts txt_again.read //Changed Line
I was looking at a Ruby script and I came across script = $0. I have done some Googling but I have not found a definite answer as to what this does. I believe that it protects you from reading a file bigger than memory, is that correct?
Thanks, I have the full script below so you can see it in context:
# Takes the name of a file as an argument and assigns to filename
filename = ARGV.first
script = $0
puts "We're going to erase #{filename}."
puts "If you don't want that, hit CTRL-C (^C)."
puts "If you do want that, hit RETURN."
print "? "
STDIN.gets
puts "Opening the file..."
target = File.open(filename, 'w')
puts "Truncating the file. Goodbye!"
target.truncate(target.size)
puts "Now I'm going to ask you for three lines."
print "line 1: "; line1 = STDIN.gets.chomp()
print "line 2: "; line2 = STDIN.gets.chomp()
print "line 3: "; line3 = STDIN.gets.chomp()
puts "I'm going to write these to the file."
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
puts "And finally, we close it."
target.close()
$0 is one of Ruby's global variables. From here:
$0 -- Contains the name of the script being executed. May be assignable.
Oh the classic Zed Shaw books! lol
The $0 gets the input on the command line before the first argument. So say you were to run this through the command line using the ruby interpreter you could put "ruby (fileName) test.txt" and $0 will pick up the fileName and save it to the variable 'script'. I'm not really sure why your doing it here because you do use it later in the program, but that's it.
The way you could have tested this would be to print it on the screen using puts, perhaps add this bit of code to see it yourself somewhere in the code:
puts "The $0 has saved #{script} to it, I wonder where it got that."
and see it will name your file.
I got the above error when trying to reduce 5 lines to 1, using target.write:
target.write("%s \n %s \n %s \n") % [line1, line2, line3]
# target.write("\n")
# target.write(line2)
# target.write("\n")
# target.write(line3)
# target.write("\n")
The commented section ran(when the 1st line was target.write(line1), but this does not.
Why isn't the very first line the same as writing the commented out six lines? here is the whole script:
filename = ARGV.first
script = $0
puts "We're going to erase #{filename}."
puts "If you don't want that hit control C"
puts "If you do want that hit execute or return"
print "? "
STDIN.gets
puts "Opening the file..."
target = File.open(filename, 'w')
puts "Truncating the file. Goodbye!"
target.truncate(target.size)
puts "Now I'm going to ask you for three lines."
print "line1: "; line1 = STDIN.gets.chomp()
print "line2: "; line2 = STDIN.gets.chomp()
print "line3: "; line3 = STDIN.gets.chomp()
puts "I'm going to write these to the file."
target.write("%s \n %s \n %s \n") % [line1, line2, line3]
# target.write("\n")
# target.write(line2)
# target.write("\n")
# target.write(line3)
# target.write("\n")
puts "And finally we close it"
target.close()
The closing paren on the target.write line is in the wrong place. Try
target.write("%s \n %s \n %s \n" % [line1, line2, line3])
Your parenthesis are wrong. What you have:
target.write("%s \n %s \n %s \n") % [line1, line2, line3]
is equivalent to doing:
a = target.write("%s \n %s \n %s \n")
a % [line1, line2, line3]
Thus what you want is:
target.write("%s \n %s \n %s \n" % [line1, line2, line3])