How to insert 't->' after '\n'? - ruby

I have a string that might have some of \n before the actual text. I want to add t-> after the new line character or characters. That means that once there is something else than '\n' in the string I want to insert 't->'.
Is there any simple way than
what = "\nrufus: ready" #result is "\nt->rufus: ready"
#what = "\n\nrufus: ready" #result is "\n\nt->rufus: ready"
#what = "\n\nrufus\n: ready" #result is "\n\nt->rufus: ready\n"
what.length.times do |i|
if (what[i,1] != "\n")
what.insert(i,"t->")
break
end
end

If I understand right, you want the following;
"abc def" => "t->abc def"
"\n\nabc def" => "\n\nt->abc def"
As such, I'd try;
string.sub(/^\n*/) do |newlines|
"#{newlines}t->"
end

If you want to insert some text at the end of every line:
original = "Hello\nWorld\nYay"
changed = original.gsub /$/, ' More!'
puts changed
#=> Hello More!
#=> World More!
#=> Yay More!

It's not a good idea to change the string as you iterate over it.
Presumably this is what you're looking for?
"\n\n".gsub("\n", "t->\n") # => "t->\nt->\n"
(substitute every instance of "\n" with "t->\n")

Related

Search through text word by word

I'd like to search through a txt file for a particular word. If I find that word, I'd like to retrieve the word that immediately follows it in the file. If my text file contained:
"My name is Jay and I want to go to the store"
I'd be searching for the word "want", and would want to add the word "to" to my array. I'll be looking through a very big text file, so any notes on performance would be great too.
The most literal way to read that might look like this:
a = []
str = "My name is Jack and I want to go to the store"
str.scan(/\w+/).each_cons(2) {|x, y| a << y if x == 'to'}
a
#=> ["go", "the"]
To read the file into a string use File.read.
This is one way:
Code
def find_next(fname, word)
enum = IO.foreach(fname)
loop do
e = (enum.next).scan(/\w+/)
ndx = e.index(word)
if ndx
return e[ndx+1] if ndx < e.size-1
loop do
e = enum.next
break if e =~ /\w+/
end
return e[/\w+/]
end
end
nil
end
Example
text =<<_
It was the best of times, it was the worst of times,
it was the age of wisdom, it was the age of foolishness,
. . . . .
it was the epoch of belief, it was the epoch of incredulity,
it was the season of light, it was the season of darkness,
it was the spring of hope, it was the winter of despair…
_
FName = "two_cities"
File.write(FName, text)
find_next(FName, "worst")
# of
find_next(FName, "wisdom")
# it
find_next(FName, "foolishness")
# it
find_next(FName, "dispair")
#=> nil
find_next(FName, "magpie")
#=> nil
Shorter, but less efficient, and problematic with large files:
File.read(FName)[/(?<=\b#{word}\b)\W+(\w+)/,1]
This is probably not the fastest way to do it, but something along these lines should work:
filename = "/path/to/filename"
target_word = "weasel"
next_word = ""
File.open(filename).each_line do |line|
line.split.each_with_index do |word, index|
if word == target_word
next_word = line.split[index + 1]
end
end
end
Given a File, String, or StringIO stored in file:
pattern, match = 'want', nil
catch :found do
file.each_line do |line|
line.split.each_cons(2) do |words|
if words[0] == pattern
match = words.pop
throw :found
end
end
end
end
match
#=> "to"
Note that this answer will find at most one match per file for speed, and linewise operation will save memory. If you want to find multiple matches per file, or find matches across line breaks, then this other answer is probably the way to go. YMMV.
This is the fastest I could come up with, assuming your file is loaded in a string:
word = 'want'
array = []
string.scan(/\b#{word}\b\s(\w+)/) do
array << $1
end
This will find ALL words that follow your particular word. So for example:
word = 'want'
string = 'My name is Jay and I want to go and I want a candy'
array = []
string.scan(/\b#{word}\b\s(\w+)/) do
array << $1
end
p array #=> ["to", "a"]
Testing this on my machine where I duplicated this string 500,000 times, I was able to reach 0.6 seconds execution time. I've also tried other approaches like splitting the string etc. but this was the fastest solution:
require 'benchmark'
Benchmark.bm do |bm|
bm.report do
word = 'want'
string = 'My name is Jay and I want to go and I want a candy' * 500_000
array = []
string.scan(/\b#{word}\b\s(\w+)/) do
array << $1
end
end
end

My instance variable isn't holding its value

Okay, so I'm building something that takes a text file and breaks it up into multiple sections that are further divided into entries, and then puts <a> tags around part of each entry. I have an instance variable, #section_name, that I need to use in making the link. The problem is, #section_name seems to lose its value if I look at it wrong. Some code:
def find_entries
#sections.each do |section|
#entries = section.to_s.shatter(/(some) RegEx/)
#section_name = $1.to_s
puts #section_name
add_links
end
end
def add_links
puts "looking for #{#section_name} in #{#section_hash}"
section_link = #section_hash.fetch(#section_name)
end
If I comment out the call to add_links, it spits out the names of all the sections, but if I include it, I just get:
looking for in {"contents" => "of", "the" => "hash"}
Any help is much appreciated!
$1 is a global variable which can be used in later code.$n contains the n-th (...) capture of the last match
"foobar".sub(/foo(.*)/, '\1\1')
puts "The matching word was #{$1}" #=> The matching word was bar
"123 456 789" =~ /(\d\d)(\d)/
p [$1, $2] #=> ["12", "3"]
So I think #entries = section.to_s.shatter(/(some) RegEx/) line is not doing match properly. thus your first matched group contains nothing. so $1 prints nil.

Why the newline char does not work here?

def say(arg)
"Hello, #{arg}.\n"
end
say("ABC") # => "Hello, ABC.\n"
Why here \n is printed instead of a newline?
because say returns a String. it doesn't print anything.
If you want to print something you should try:
def say(arg)
puts "Hello, #{arg}.\n"
end
You're most likely trying this in irb which displays the Ruby representation of a string. Compare:
irb(main):007:0> puts say("ABC") + say("ABC")
Hello, ABC.
Hello, ABC.
=> nil
irb(main):008:0> puts "ABC" + "ABC"
ABCABC
=> nil
It is actually never printed to stdio or anything like that, you are simply returning a string from a function.
I'll make the assumption that you are evaluating this in IRB, IRB prints out the result of every expression.
use puts or similar.

Ruby grep with line number

What could be the best way of getting the matching lines with the line numbers using Ruby's Enumerable#grep method. (as we use -n or --line-number switch with grep command).
Enumerable#grep doesn't let you do that, at least by default. Instead, I came up with:
text = 'now is the time
for all good men
to come to the aid
of their country'
regex = /aid/
hits = text.lines.with_index(1).inject([]) { |m,i| m << i if (i[0][regex]); m }
hits # => [["to come to the aid\n", 3]]
maybe something like this:
module Enumerable
def lgrep(pattern)
map.with_index.select{|e,| e =~ pattern}
end
end
This isn't elegant or efficient, but why not just number the lines before grepping?
You can kludge it in Ruby 1.8.6 like so:
require 'enumerator'
class Array
def grep_with_index(regex)
self.enum_for(:each_with_index).select {|x,i| x =~ regex}
end
end
arr = ['Foo', 'Bar', 'Gah']
arr.grep_with_index(/o/) # => [[0, 'Foo']]
arr.grep_with_index(/a/) # => [[1, 'Bar'], [2, 'Gah']]
Or if you're looking for tips on writing a grep-like utility in Ruby. Something like this should work:
def greplines(filename, regex)
lineno = 0
File.open(filename) do |file|
file.each_line do |line|
puts "#{lineno += 1}: #{line}" if line =~ regex
end
end
end
>> lines=["one", "two", "tests"]
=> ["one", "two", "tests"]
>> lines.grep(/test/){|x| puts "#{lines.index(x)+1}, #{x}" }
3, tests
To mash up the Tin Man's and ghostdog74's answers
text = 'now is the time
for all good men
to come to the aid
of their country'
regex = /aid/
text.lines.grep(/aid/){|x| puts "#{text.lines.find_index(x)+1}, #{x}" }
# => 3, to come to the aid
A modification to the solution given by the Tin Man. This snippet will return a hash having line numbers as keys, and matching lines as values. This one also works in ruby 1.8.7.
text = 'now is the time
for all good men
to come to the aid
of their country'
regex = /aid/
hits = text.lines.each_with_index.inject({}) { |m, i| m.merge!({(i[1]+1) => i[0].chomp}) if (i[0][regex]); m}
hits #=> {3=>"to come to the aid"}
Put text in a file
test.log
now is the time
for all good men
to come to the aid
of their country
Command line (alternative of grep or awk command )
ruby -ne ' puts $_ if $_=~/to the/' test.log
Try this also
ruby -na -e ' puts $F[2] if $_=~/the/' test.log
Similarly
ruby -na -e ' puts $_.split[2] if $_=~/the/' test.log
This is similar to awk command.
Another suggestion:
lines.find_index{ |l| l=~ regex }.

How to do a newline in output

How do I make \n actually work in my output? At the moment it just writes it all in 1 long block. Thanks for any help
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
#new = ''
playlist_name = gets.chomp + '.m3u'
music.each do |z|
#new += z + '\n'
end
File.open playlist_name, 'w' do |f|
f.write #new
end
Use "\n" instead of '\n'
I would like to share my experience with \n
I came to notice that "\n" works as-
puts "\n\n" // to provide 2 new lines
but not
p "\n\n"
also
puts '\n\n'
Doesn't works.
Hope will work for you!!
You can do this all in the File.open block:
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
playlist_name = gets.chomp + '.m3u'
File.open playlist_name, 'w' do |f|
music.each do |z|
f.puts z
end
end
Actually you don't even need the block:
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
playlist_name = gets.chomp + '.m3u'
File.open(playlist_name, 'w').puts(music)
For me it didn't work with adding "\n" to the end of an existing argument to puts, so as a workaround I called print on the next line with "\n" as an argument, although I suppose I could have just called puts again.
This did not produce the desired result:
puts "Coach says: #{coach_answer(user_input)}\n"
But this did:
puts "Coach says: #{coach_answer(user_input)}"
print "\n"

Resources