How to actually write a newline to a string - ruby

How can I make this
content[i].gsub("\n", "\\n")
write (something like) this to a file
str = "some text\n"
I'm writing a piece of code to take a file and build a single string out of it that can be inserted back into the source code your working with, if that helps at all
If I'm mistaken and my error is actually somewhere else in the code, here is:
#!/bin/usr/ruby
#reads a file and parses into a single string declaration in language of choice
#another little snippet to make my job easier when writing lots of code
#programmed by michael ward
# h3xc0ntr0l#gmail.com | gists.github.com/michaelfward
# ***************************************
# example scrips
# with writefiles
# | writefiles [file with paths] [file to write*]
# | makestring [file to write* (actually is read, but same as above)] [lang]
#****************************************
def readFile(path)
fd = File.open(path, "r")
content = []
fd.each_line {|x| content.push(x)}
content = fixnewlines(content)
str = content.join()
str
end
def fixnewlines(content)
content.each_index do |i|
content[i].gsub("\n", "\\n")
end
end
def usage
puts "makestring [file to read] [language output]"
exit
end
langs = {"rb"=>"str =", "js" => "var str =", "c"=> "char str[] ="}
usage unless ARGV.length == 2
lang = ARGV[1]
path = ARGV[0]
str = readFile(path)
if langs[lang] == nil
if lang == "c++" || lang == "cpp" || lang == "c#"
puts "#{lang[c]}#{str}"
else
puts "unrecognized language found. supported languages are"
langs.each_key {|k| puts " #{k}"}
exit
end
else
puts "#{langs[lang]} #{str}"
end

Just remove fixnewlines and change readFile:
def readFile(path)
File.read(path).gsub("\n", '\n')
end
Hope it helps. On Windows use \r\n instead of \n. There's no need to escape slashes inside single brackets.

It depends on which platform you're using. Unix uses \n as line ending characters, whereas windows uses \r\n. It looks like you're replacing all new line characters though with \\n which escapes the new line character which I would not expect to work on either platform.

Related

Ruby - How to skip 2 lines after reading a blank line from file

I have this loop:
File.open(path_to_file, "r") do |infile|
infile.each_line do |line|
#do things with line
end
end
And what I want to do:
If the current line is blank "/^[\s]*$\n/" skip the next 2 lines and continue reading from there.
For such situation, I would do something like this:
file = File.open(path_to_file, "r")
while !file.eof?
line = file.gets
if line.match(/^[\s]*$\n/)
2.times{ file.gets if !file.eof? }
else
# do something with line
end
end
Let's first create a test file.
str =
" \nNow is \nthe time \n \nfor all \ngood \npeople \n\nto \nsupport\na nasty\n \nperson\n"
puts str
#
# Now is
# the time
#
# for all
# good
# people
#
# to
# support
# a nasty
#
# person
#=> nil
FName = "almost_over"
IO.write(FName, str)
#=> 75
Let's confirm the file was written correctly.
IO.read(FName) == str
#=> true
We can skip the unwanted lines as follows.
count = 0
IO.foreach(FName) do |line|
if count > 0
count -=1
elsif line.strip.empty?
count = 2
else
puts "My code using the line '#{line.strip}' goes here"
end
end
# My code using the line 'people' goes here
# My code using the line 'a nasty' goes here
#=> nil
As File is a subclass of IO (File < IO #=> true), you will often see expressions using IO methods with File as the receiver (e.g., File.read(FName)).

How to enter values, save them to a new file and search for the values in the file

I have a school assignment that I need help with.
This is the description of the assignment:
Ruby program that can hold these values:
Artifacts
Values
Assumptions
It shall be possible for a user:
To enter these three types of values.
Search for a value of type Artifacts, Values or Assumptions.
The program shall use loops and at least one class definition.
The only function that won't work out for me are these lines:
f= File.new("Artefacts", "r")
puts "Search for information regarding cultural information"
userinput = gets.chomp
if File.readlines("Artefacts").include?('userinput')
puts "We have found your input."
else
puts "We have not found your input."
f.close
No matter what the user inserts, it only displays "We have not found your input".
Part A: get user input and write to file
def write_to_file(path, string)
# 'a' means append
# it will create the file if it doesnt exist
File.open(path, 'a') do |file|
file.write string + "\n"
end
end
path = "Artefacts"
num_inputs = 3
num_inputs.times do |i|
puts "enter input (#{i + 1} / #{num_inputs}):"
write_to_file path, gets.chomp
end
puts `cat #{path}`
# if you entered "foo" for each input,
# this will show:
# foo
# foo
# foo
Part B: read a file and check if it contains a string:
path = "./Artefacts"
query = "foo"
text = File.read path
# this will be a string with all the text
lines = File.readlines path
# this will be an array of strings (one for each line)
is_text_found = text.include? query
# or
is_text_found = lines.any? do |line|
line.include? query
end

Replace whole line with sub-string in a text file - Ruby

New to ruby here!
How to replace the whole line in a text file which contains a specific string using ruby?
Example: I want to remove and add the whole line contains "DB_URL" and add something like "DB_CON=jdbc:mysql:replication://master,slave1,slave2,slave3/test"
DB_URL=jdbc:oracle:thin:#localhost:TEST
DB_USERNAME=USER
DB_PASSWORD=PASSWORD
Here is your solution.
file_data = ""
word = 'Word you want to match in line'
replacement = 'line you want to set in replacement'
IO.foreach('pat/to/file.txt') do |line|
file_data += line.gsub(/^.*#{Regexp.quote(word)}.*$/, replacement)
end
puts file_data
File.open('pat/to/samefile.txt', 'w') do |line|
line.write file_data
end
Here is my attempt :
file.txt
First line
Second line
foo
bar
baz foo
Last line
test.rb
f = File.open("file.txt", "r")
a = f.map do |l|
(l.include? 'foo') ? "replacing string\n" : l # Please note the double quotes
end
p a.join('')
Output
$ ruby test.rb
"First line\nSecond line\nreplacing string\nbar\nreplacing string\nLast line"
I commented # Please note the double quotes because single quotes will escape the \n (that will become \\n). Also, you might want to think about the last line of your file since it will add \n at the end of the last line when there will not have one at the end of your original file. If you don't want that you could make something like :
f = File.open("file.txt", "r")
a = f.map do |l|
(l.include? 'foo') ? "replacing string\n" : l
end
a[-1] = a[-1][0..-2] if a[-1] == "replacing string\n"
p a.join('')

Regular Expression matching in ruby, checking for white space

I am trying to check a file for white spaces at the beginning of each line. I want the white-space at the beginning of the line to be consistent, all start with spaces or all start with tabs. I wrote the code below but it isn't working for me. If there exist a space at a beginning of one line and then a tab exists in the beginning of another line print a warning or something.
file = File.open("file_tobe_checked","r") #I'm opening the file to be checked
while (line = file.gets)
a=(line =~ /^ /).nil?
b=(line =~/^\t/).nil?
if a==false && b==false
print "The white spaces at the beginning of each line are not consistent"
end
end
file.close
This is one solution where you don't read the file or the extracted lines array twice:
#!/usr/bin/env ruby
file = ARGV.shift
tabs = spaces = false
File.readlines(file).each do |line|
line =~ /^\t/ and tabs = true
line =~ /^ / and spaces = true
if spaces and tabs
puts "The white spaces at the beginning of each line are not consistent."
break
end
end
Usage:
ruby script.rb file_to_be_checked
And it may be more efficient to compare lines with these:
line[0] == "\t" and tabs = true
line[0] == ' ' and spaces = true
You can also prefer to use each_line over readlines. Perhaps each_line allows you to read the file line by line instead of reading all the lines in one shot:
File.open(file).each_line do |line|
How important is it that you check for the whitespace (and warn/notify accordingly)? If you are aiming to just correct the whitespace, .strip is great at taking care of errant whitespace.
lines_array = File.readlines(file_to_be_checked)
File.open(file_to_be_checked, "w") do |f|
lines_array.each do |line|
# Modify the line as you need and write the result
f.write(line.strip)
end
end
I assume that no line can begin with one or more spaces followed by a tab, or vice-versa.
To merely conclude that there are one or more inconsistencies within the file is not very helpful in dealing with the problem. Instead you might consider giving the line number of the first line that begins with a space or tab, then giving the line numbers of all subsequent lines that begin with a space or tab that does not match the first line found with such. You could do that as follows (sorry, untested).
def check_file(fname)
file = File.open(fname,"r")
line_no = 0
until file.eof?
first_white = file.gets[/(^\s)/,1]
break if first_white
line_no += 1
end
unless file.eof?
puts "Line #{line_no} begins with a #{(first_white=='\t') ? "tab":"space"}"
until file.eof?
preface = file.gets[/(^\s)/,1))]
puts "Line #{line_no} begins with a #{(preface=='\t') ? "tab":"space"}" \
if preface && preface != first_white
line_no += 1
end
end
file.close
end

ruby - how to correctly parse varying numbers of command line arguments

n00b question alert!
here is the problem:
I am creating a shell script that takes a minimum of 3 arguments: a string, a line number, and at least one file.
I've written a script that will accept EXACTLY 3 arguments, but I don't know how to handle multiple file name arguments.
here's the relevant parts of my code (skipping the writing back into the file etc):
#!/usr/bin/env ruby
the_string = ARGV[0]
line_number = ARGV[1]
the_file = ARGV[2]
def insert_script(str, line_n, file)
f = file
s = str
ln = line_n.to_i
if (File.file? f)
read_in(f,ln,s)
else
puts "false"
end
end
def read_in(f,ln,s)
lines = File.readlines(f)
lines[ln] = s + "\n"
return lines
end
# run it
puts insert_script(the_string, line_number, the_file)
now I know that it's easy to write a block that will iterate through ALL the arguments:
ARGV.each do |a|
puts a
end
but I need to ONLY loop through the args from ARGV[2] (the first file name) to the last file name.
I know there's got to be - at a minimum - at least one easy way to do this, but I just can't see what it is at the moment!
in any case - I'd be more than happy if someone can just point me to a tutorial or an example, I'm sure there are plenty out there - but I can't seem to find them.
thanks
Would you consider using a helpful gem? Trollop is great for command line parsing because it automatically gives you help messages, long and short command-line switches, etc.
require 'trollop'
opts = Trollop::options do
opt :string, "The string", :type => :string
opt :line, "line number", :type => :int
opt :file, "file(s)", :type => :strings
end
p opts
When I call it "commandline.rb" and run it:
$ ruby commandline.rb --string "foo bar" --line 3 --file foo.txt bar.txt
{:string=>"foo bar", :line=>3, :file=>["foo.txt", "bar.txt"], :help=>false, :string_given=>true, :line_given=>true, :file_given=>true}
If you modify the ARGV array to remove the elements you're no longer interested in treating as filenames, you can treat all remaining elements as filenames and iterate over their contents with ARGF.
That's a mouthful, a small example will demonstrate it more easily:
argf.rb:
#!/usr/bin/ruby
str = ARGV.shift
line = ARGV.shift
ARGF.each do |f|
puts f
end
$ ./argf.rb one two argf.rb argf.rb
#!/usr/bin/ruby
str = ARGV.shift
line = ARGV.shift
ARGF.each do |f|
puts f
end
#!/usr/bin/ruby
str = ARGV.shift
line = ARGV.shift
ARGF.each do |f|
puts f
end
$
There are two copies of the argf.rb file printed to the console because I gave the filename argf.rb twice on the command line. It was opened and iterated over once for each mention.
If you want to operate on the files as files, rather than read their contents, you can simply modify the ARGV array and then use the remaining elements directly.
The canonical way is to use shift, like so:
the_string = ARGV.shift
line_number = ARGV.shift
ARGV.each do |file|
puts insert_script(the_string, line_number, the_file)
end
Take a look at OptionParser - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html. It allows you to specify the number of arguments, whether they are mandatory or optional, handle errors such as MissingArgument or InvalidOption.
An alternate (and somewhat uglier) trick if you don't want to use another library or change the ARGV array is to use .upto
2.upto(ARGV.length-1) do |i|
puts ARGV[i]
end

Resources