How to append a new line write to a file with ruby? - ruby

My code is:
def write_to_file(line, my_file)
File.open(my_file, 'a') do |file|
p '-----loop number:' + line.id.to_s
file.puts "#{line.id}"
end
end
If I loop three times with this method, I can see:
-----loop number:1
-----loop number:2
-----loop number:3
But it can only write the last id into my_file. Even I tried:
file << "#{line.id}"
# or
file.write "#{line.id}\n"
The result was the same.

try this
def write_to_file(line, my_file)
File.open(my_file, 'a') do |file|
p '-----loop number:' + line.to_s
file.puts "#{line}"
end
end
[1,2,3,4].each do |line|
write_to_file(line, my_file)
end

Related

Ruby: Put multiple lines from file

Right, so I have a file in which I want to get two different strings
text.txt:
abc
def
ghi
jkl
abc
ghi
How would I go about reading this and printing out two lines?
I'm currently here:
File.open(filename) do |f|
f.each_line do |line|
if line =~ /abc/
puts "Current things: #{line}"
end
end
end
I was thinking something like this (which obv doesn't work hence the question)
File.open(filename) do |f|
f.each_line do |line,line2|
if line =~ /abc/ and line2 =~ /ghi/
puts "Current things: #{line} #{line2}"
end
end
end
Am I WAY out on this one?
expected output:
Current things: abc ghi
An alternative, a bit shorter solution:
lines = File.foreach(filename, chomp: true).each_with_object([]) do |line, arr|
arr << line if line.match?(/abc|ghi/)
end
puts "Current things: #{lines.join(' ')}" if lines.any?
# => Current things: abc ghi abc ghi
If you want unique lines:
require 'set'
lines = File.foreach(filename, chomp: true).each_with_object(Set.new) do |line, set|
set.add(line) if line.match?(/abc|ghi/)
end
puts "Current things: #{lines.to_a.join(' ')}" if lines.any?
# => Current things: abc ghi
You could use an array to store the matching lines and then print them when finished iterating.
File.open(filename) do |f|
matching_lines = []
f.each_line do |line|
if line =~ /abc/ || line =~ /ghi/
matching_lines << line
end
end
puts "Current things: #{matching_lines.join(' ')}" unless matching_lines.empty?
end

ruby How I could print without leave newline space for each line?

ruby How I could print without leave newline space for each line
this is my file
name1;name2;name3
name4;name5;name6
I have this command
File.open("text2xycff.txt", "r") do |fix|
fix.readlines.each do |line|
parts = line.chomp.split(';')
input3= zero
File.open('text2xyczzzz2.txt', 'a+') do |f|
f.puts parts[0] , parts[1], parts[2] ,input3
end
end
end
this is my output
name1
name2
name3
zero
name4
name5
name6
zero
I need to output this
name1;name2;name3;zero
name4;name5;name6;zero
Please help me whit this problem
A more minimal approach is to just append something to each line:
File.open("text2xycff.txt", "r") do |input|
File.open('text2xyczzzz2.txt', 'a+') do |output|
input.readlines.each do |line|
output.puts(line.chomp + ';zero')
end
end
end
Or if you want to actually parse things, which presents an opportunity for clean-up:
File.open("text2xycff.txt", "r") do |input|
File.open('text2xyczzzz2.txt', 'a+') do |output|
input.readlines.each do |line|
parts = line.chomp.split(/;/)
parts << 'zero'
output.puts(parts.join(';'))
end
end
end
You have two solutions.
The first one uses puts as you currently do:
File.open('yourfile.txt', 'a+') { |f|
f.puts "#{parts[0]}#{parts[1]}#{parts[2]}#{input3}"
}
The second one uses write instead of puts:
File.open('yourfile.txt', 'a+') { |f|
f.write parts[0]
f.write parts[1]
f.write parts[2]
f.write input3
}
If you call puts with comma-separated arguments, each one of them will be printed on a different line.
You can use ruby string interpolation here (http://ruby-for-beginners.rubymonstas.org/bonus/string_interpolation.html):
f.puts "#{parts[0]};#{parts[1]};#{parts[3]};#{input3}"
Try:
File.open("test_io.txt", "r") do |fix|
fix.readlines.each do |line|
File.open('new_file10.txt', 'a+') do |f|
next if line == "\n"
f.puts "#{line.chomp};zero"
end
end
end
I'm not sure why you're splitting the string by semicolon when you specified you wanted the below output. You would be better served just appending ";zero" to the end of the string rather than parsing an array.
name1;name2;name3;zero
name4;name5;name6;zero
You can specify an if statement to check for the zero value.
Example:
arr = ["name1", "name2", "name3", "zero", "name4", "name5", "name6", "zero"];
arr.each { |x|
if x != "zero" then
print x
else
puts x
end
}
Output:
name1name2name3zero
name4name5name6zero
print will print inline.
puts will print on a new line.
Just implement this logic in your code and you're good to go.

Disable creating files and directories while execution

I've just started learning ruby and I'm trying to edit the following script. The code as is downloads files while creating directories.
def download_files
puts "Downloading #{#base_url} to #{backup_path} from site..."
puts
file_list_by_time = get_file_list_by_time
if file_list_by_time.count == 0
puts "No files to download. Possible reasons:\n\t* Accept regex didn't let any files through (Accept Regex: \"#{#accept_regex.to_s}\")\n\t* Site is not in site."
return
end
count = 0
file_list_by_time.each do |file_remote_info|
count += 1
file_url = file_remote_info[:file_url]
file_id = file_remote_info[:file_id]
file_time = file_remote_info[:time]
file_path_elements = file_id.split('/')
if file_id == ""
dir_path = backup_path
file_path = backup_path + 'index.html'
elsif file_url[-1] == '/' or not file_path_elements[-1].include? '.'
dir_path = backup_path + file_path_elements[0..-1].join('/')
file_path = backup_path + file_path_elements[0..-1].join('/') + '/index.html'
else
dir_path = backup_path + file_path_elements[0..-2].join('/')
file_path = backup_path + file_path_elements[0..-1].join('/')
end
unless File.exists? file_path
open('myfile.txt', 'a') do |f|
f.puts ("http://example.com/#{file_time}id_/#{file_url}")
end
begin
structure_dir_path dir_path
open(file_path, "wb") do |file|
begin
rescue OpenURI::HTTPError => e
puts "#{file_url} # #{e}"
file.write(e.io.read)
rescue StandardError => e
puts "#{file_url} # #{e}"
end
end
rescue StandardError => e
puts "#{file_url} # #{e}"
end
puts "#{file_url} -> #{file_path} (#{count}/#{file_list_by_time.size})"
else
puts "#{file_url} # #{file_path} already exists. (#{count}/#{file_list_by_time.size})"
end
end
puts
puts "Download complete, saved in #{backup_path} (#{file_list_by_time.size} files)"
end
end
I want to change it to just save the full file URL to a text file i.e. save the URL without downloading the file.
I added the following to the code which works perfectly. I now just need to stop the script from downloading the files.
open('myfile.txt', 'a') do |f|
f.puts ("http://example.com/#{file_time}id_/#{file_url}")
end
i tried removing the part from structure_dir_path dir_path to the end but i keep getting an error message. Any ideas how can i implement that correctly?
Return Early from Method
To stop processing, just return from anywhere inside your method, including from within a block. For example:
open('myfile.txt', 'a') do |f|
url = "http://example.com/#{file_time}id_/#{file_url}"
f.puts url
return url
end

I want only the files that contain def to be displayed. But this code displays all files. How to solve?

I have been trying to display as "file name def statements..." But this code is not helping.
files = Dir.entries("C:\\Users\\itcuser\\Desktop\\Ruby Programs").select {|f| !File.directory? f}
files.each do |file_name|
if !File.directory? file_name
File.open(file_name) do |f|
**puts file_name**
f.any? do |line|
if line.include?("def")
print line
end
end
end
end
end
Well, you're not using the return value of your f.any? to print the filename. Should be more like this instead.
File.open(file_name) do |f|
puts file_name if f.any? { |line| line.include?("def") }
end
Try this:
files = Dir.entries("C:\\Users\\itcuser\\Desktop\\Ruby Programs")
files.each do |file_name|
# skip this, if file_name is a directory
next if File.directory? file_name
lines = File.readlines(filename)
puts file_name if lines.any? { |line| line.include?('def')
end

Trying to compare two text files, and create a third based on information

I have two text files, master.txt and 926.txt. If there is a line in 926.txt that is not in master.txt, I want to write to a new file, notinbook.txt.
I wrote the best thing I could think of, but given that I'm a terrible/newbie programmer it failed. Here's what I have
g = File.new("notinbook.txt", "w")
File.open("926.txt", "r") do |f|
while (line = f.gets)
x = line.chomp
if
File.open("master.txt","w") do |h|
end
while (line = h.gets)
if line.chomp != x
puts line
end
end
end
end
end
g.close
Of course, it fails. Thanks!
This should work:
f1 = IO.readlines("926.txt").map(&:chomp)
f2 = IO.readlines("master.txt").map(&:chomp)
File.open("notinbook.txt","w"){ |f| f.write((f1-f2).join("\n")) }
This was my test:
926.txt
line1
line2
line3
line4
line5
master.txt
line1
line2
line4
notinbook.txt
line3
line5
You can do something like this:
master_lines = []
File.open("notinbook.txt","w") do |result|
File.open("master.txt","r") do |master|
master.each_line do |line|
master_lines << line.chomp
end
end
File.open("926.txt","r") do |query|
query.each_line do |line|
if !master_lines.include? line.chomp
result.puts line.chomp
end
end
end
end
Use : http://raa.ruby-lang.org/project/compare/
OR
%x(diff file1 file2)
OR
http://github.com/myobie/htmldiff/
Hope this helps
dir = File.dirname(__FILE__)
notinbook = "#{dir}/notinbook.txt"
master = "#{dir}/master.txt"
f926 = "#{dir}/926.txt"
def file_into_ary(file)
ary = []
File.open(file).each{ |line| ary << line }
return ary
end
def write_difference(file, diff)
File.open(file, 'w') do |file|
diff.each do |line|
file.write(line)
end
end
end
diff = file_into_ary(f926) - file_into_ary(master)
write_difference(notinbook, diff) unless diff.empty?

Resources