Ruby find string in file and print result - ruby-on-rails

It's been a very long time since I've used ruby for things like this but, I forget how to open a file, look for a string, and print what ruby finds. Here is what I have:
#!/usr/bin/env ruby
f = File.new("file.txt")
text = f.read
if text =~ /string/ then
puts test
end
I want to determine what the "document root" (routes) is in config/routes.rb
If I print the string, it prints the file.
I feel dumb that I don't remember what this is, but I need to know.
Hopefully, I can make it print this:
# Route is:
blah blah blah blah

File.open 'file.txt' do |file|
file.find { |line| line =~ /regexp/ }
end
That will return the first line that matches the regular expression. If you want all matching lines, change find to find_all.
It's also more efficient. It iterates over the lines one at a time, without loading the entire file into memory.
Also, the grep method can be used:
File.foreach('file.txt').grep /regexp/

The simplest way to get the root is to do:
rake routes | grep root
If you want to do it in Ruby, I would go with:
File.open("config/routes.rb") do |f|
f.each_line do |line|
if line =~ /root/
puts "Found root: #{line}"
end
end
end

Inside text you have the whole file as a string, you can either match against it using a .match with regexp or as Dave Newton suggested you can just iterate over each line and check.
Something such as:
f.each_line { |line|
if line =~ /string/ then
puts line
end
}

Related

Find a specific text segment within a file and than search for specific line in ruby

I'm trying to find a specific text segment within a text file and than a specific line within the text segment. The algorithm should be as follow:
1)First, search for a line which contains the keyword "Macros"
2)The next found line must contain the keyword "Name"
3)And finally print me the next line
As pseudo code I mean something like this:
File.open(file_name) do |f|
f.each_line {|line|
if line.include?("Macros")
and if next line.include?("Name")
print me the line after
end
Any suggestions?
I would use boolean flags to remember that I already matched the parts of the condition:
File.open(file_name) do |file|
marcos_found = false
name_found = false
file.each_line do |line|
if line.include?('Macros')
marcos_found = true
elsif found_marcos && line.include?("Name")
name_found = true
elsif marcos_found && name_found
puts line
break # do not search further or print later matches
end
end
end
You could use a regex:
r = /
\bMacros\b # Match "Macros" surrounded by word breaks
.*?$ # Match anything lazily to the end of the line
[^$]* # Match anything lazily other than a line break
\bName\b # Match "Name" surrounded by word breaks
.*?\n # Match anything lazily to the end of the line
\K # Discard everything matched so far
.*?$ # Match anything lazily to the end of the line
/x # Extended/free-spacing mode
Suppose:
text = <<-_
You can use
Macros in C
to replace code.
Ruby doesn't
have Macros.
"Name That Tune"
was an old TV
show.
_
Let's write this to file:
FName = "test"
File.write(FName, text)
#=> 104
read it back into a string:
str = File.read(FName)
#=> "You can use\nMacros in C\nto replace code.\nRuby doesn't\nhave " +
# "Macros.\n\"Name That Tune\"\nwas an old TV\nshow.\n"
and test the regex:
text.scan r
#=> ["was an old TV"]

Remove trailing white-spaces from each line in a file

I am using ruby and I want to remove trailing white-spaces at the end of each line in a file.
One way to do this,
iterate line by line and save it in another file and then replace new file with the old one.
temp_file = Tempfile.new("temp")
f.each_line do |line|
new_line = line.rstrip
temp_file.puts new_line
end
but this is not what I want.
I want to use the method which we generally use in C,C++ without using any temporary file that is, move file pointer to the front of line by new line and overwrite it.
How can we do this in ruby ??
Here is the one way to modify the file content in place.
# a.rb
File.open "#{__dir__}/out1.txt", 'r+' do |io|
r_pos = w_pos = 0
while (io.seek(r_pos, IO::SEEK_SET); io.gets)
r_pos = io.tell
io.seek(w_pos, IO::SEEK_SET)
# line read in by IO#gets will be returned and also assigned to $_.
io.puts $_.rstrip
w_pos = io.tell
end
io.truncate(w_pos)
end
Here is the output of the file.
[arup#Ruby]$ cat out1.txt
foo
biz
bar
[arup#Ruby]$ ruby a.rb
[arup#Ruby]$ cat out1.txt
foo
biz
bar
[arup#Ruby]$
You can use something like:
file_name = 'testFile.txt'
input_content = File.open(file_name).read
output_content = []
file.each_line do |line|
line.gsub!("\n",'').strip!
output_content << line
end
File.open(file_name,'w').write(output_content.join("\n"))

List Rails I18n strings with full keys

I'd like to be able to generate a complete list of all the I18n keys and values for a locale including the full keys. In other words if I have these files:
config/locales/en.yml
en:
greeting:
polite: "Good evening"
informal: "What's up?"
config/locales/second.en.yml
en:
farewell:
polite: "Goodbye"
informal: "Later"
I want the following output:
greeting.polite: "Good evening"
greeting.informal: "What's up?"
farewell.polite: "Goodbye"
farewell.informal: "Later"
How do I do this?
Once loaded into memory it's just a big Hash, which you can format any way you want. to access it you can do this:
I18n.backend.send(:translations)[:en]
To get a list of available translations (created by you or maybe by plugins and gems)
I18n.available_locales
Nick Gorbikoff's answer was a start but did not emit the output I wanted as described in the question. I ended up writing my own script get_translations to do it, below.
#!/usr/bin/env ruby
require 'pp'
require './config/environment.rb'
def print_translations(prefix, x)
if x.is_a? Hash
if (not prefix.empty?)
prefix += "."
end
x.each {|key, value|
print_translations(prefix + key.to_s, value)
}
else
print prefix + ": "
PP.singleline_pp x
puts ""
end
end
I18n.translate(:foo)
translations_hash = I18n.backend.send(:translations)
print_translations("", translations_hash)
Here's a working version of a method you can use to achieve your desired output
def print_tr(data,prefix="")
if data.kind_of?(Hash)
data.each do |key,value|
print_tr(value, prefix.empty? ? key : "#{prefix}.#{key}")
end
else
puts "#{prefix}: #{data}"
end
end
Usage:
$ data = YAML.load_file('config/locales/second.en.yml')
$ print_tr(data)
=>
en.farewell.polite: "Goodbye"
en.farewell.informal: "Later"

Newbie: text replacement in my case

In my Ruby on Rails app, I have a method in my helper which opened a file by:
content = File.open(myfile.txt)
The content of the file is like:
my.car , my.seat, my.age;
my.son , my.dog, my.chair;
...
So, I split the content by ";" like following:
content.split(';').each do |line|
#Here, I want to replace the text from "my" to "her" on each line
end
How to replace each line's "my" to "her" in the content?
that's to update content to:
her.car , her.seat, her.age;
her.son , her.dog, her.chair;
...
-------------------------- update ---------------------------------
I would like to update the content of the opened file , not only replace the string when read the content from the ruby code.
There is no way to modify the content of a file on the fly. Files can only be appended, they cannot be expanded, so you cannot replace my with her.
You can start from this basic code:
buf = ""
File.open('myfile.txt') do |file|
file.readlines.each do |line|
buf << line.gsub('my', "her")
end
end
File.open('myfile.txt', 'w') do |file|
file << buf
end
line.gsub!(/my/, "her")
Although you may want to get more specific with the regular expression, e.g.
line.gsub!(/\bmy\./, "her")

How do I read line by line a text file in ruby (hosting it on s3)?

I know I've done this before and found a simple set of code, but I cannot remember or find it :(.
I have a text file of records I want to import into my Rails 3 application.
Each line represents a record. Potentially it may be tab delimited for the attributes, but am fine with just a single value as well.
How do I do this?
File.open("my/file/path", "r").each_line do |line|
# name: "Angela" job: "Writer" ...
data = line.split(/\t/)
name, job = data.map{|d| d.split(": ")[1] }.flatten
end
Related topic
What are all the common ways to read a file in Ruby?
You want IO.foreach:
IO.foreach('foo.txt') do |line|
# process the line of text here
end
Alternatively, if it really is tab-delimited, you might want to use the CSV library:
File.open('foo.txt') do |f|
CSV.foreach(f, col_sep:"\t") do |csv_row|
# All parsed for you
end
end
IO.foreach("input.txt") do |line|
out.puts line
# You might be able to use split or something to get attributes
atts = line.split
end
Have you tried using OpenURI (http://ruby-doc.org/stdlib-2.1.2/libdoc/open-uri/rdoc/OpenURI.html)? You would have to make your files accessible from S3.
Or try using de aws-sdk gem (http://aws.amazon.com/sdk-for-ruby).
You can use OpenURI to read remote or local files.
Assuming that your model has an attachment named file:
# If object is stored in amazon S3, access it through url
file_path = record.file.respond_to?(:s3_object) ? record.file.url : record.file.path
open(file_path) do |file|
file.each_line do |line|
# In your case, you can split items using tabs
line.split("\t").each do |item|
# Process item
end
end
end

Resources