why is Chef File search_file_replace not working - ruby

I am trying to get this code to replace one attribute and value but it erases the whole line.
ruby_block "update connection pool" do
block do
fe = Chef::Util::FileEdit.new(servlet_xml_path)
fe.search_file_replace("maxPoolSize=\"[0-9]+\"", "maxPoolSize=\"20\"")
fe.write_file
end
end
The function works if I have a simpler regex like:
fe.search_file_replace("maxPoolSize=", "maxPoolSize2=")

ShellFish provided the answer I was looking for.
fe.search_file_replace(/maxPoolSize="[0-9]+"/, 'maxPoolSize="20"')! –

Related

Qt : Reading the text file and Displaying in LineEdit

I have an input file and a batch file. When the batch file is executed using the System command,
a corresponding outfile is generated.
Now I want a particular text (position 350 to 357) from that outfile to be displayed on to my lineedit widget
Here is that part of my code:
system("C:/ORG_Class0178.bat")
Now the outfile will be generated
File.open("C:/ORG_Class0178_out.txt", 'r').each do |line|
var = line[350..357]
puts var
# To test whether the file is being read.
#responseLineEdit = Qt::LineEdit.new(self)
#responseLineEdit.setFont Qt::Font.new("Times NEw Roman", 12)
#responseLineEdit.resize 100,20
#responseLineEdit.move 210,395
#responseLineEdit.setText("#{var}")
end
When I do test whether the file is being read using puts statement, I get the exact required output in editor. However, the same text is not being displayed on LineEdit. Suggestions are welcome.
EDIT: A wired observation here. It works fine when I try to read the input file and display it , however it does not work with the output file. The puts statement does give the answer in editor confirming that output file does contain the required text. I am confused over this scenario.
There is nothing wrong with the code fragments shown.
Note that var is a local variable. Are the second and third code fragments in the same context? If they are in the same method, and var is not touched in-between, it will work.
If the fragments belong to different methods of the same class, than an instance variable (#var) will solve the problem.
If all that does not help, use Pry to chase the problem. Follow the link to find the pre-requisites and how to use. Place binding.pry in your code, and your program will stop at that line. Then inspect what your variables are doing.
try 'rb' instead of 'r'
File.open("C:/ORG_Class0178_out.txt", 'rb').each do |line|
var = line[350..357]
puts var

Ruby - Files - gets method

I am following Wicked cool ruby scripts book.
here,
there are two files, file_output = file_list.txt and oldfile_output = file_list.old. These two files contain list of all files the program went through and going to go through.
Now, the file is renamed as old file if a 'file_list.txt' file exists .
then, I am not able to understand the code.
Apparently every line of the file is read and the line is stored in oldfile hash.
Can some one explain from 4 the line?
And also, why is gets used here? why cant a .each method be used to read through every line?
if File.exists?(file_output)
File.rename(file_output, oldfile_output)
File.open(oldfile_output, 'rb') do |infile|
while (temp = infile.gets)
line = /(.+)\s{5,5}(\w{32,32})/.match(temp)
puts "#{line[1]} ---> #{line[2]}"
oldfile_hash[line[1]] = line[2]
end
end
end
Judging from the redundant use of quantifiers ({5,5} and {32,32}) in the regex (which would be better written as {5}, {32}), it looks like the person who wrote that code is not a professional Ruby programmer. So you can assume that the choice taken in the code is not necessarily the best.
As you pointed out, the code could have used each instead of while with gets. The latter approach is sort of an old-school Ruby way of doing it. There is nothing wrong in using it. Until the end of file is reached, gets will return a string, and when it does reach the end of file, gets will return nil, so the while loop works as the same when you use each; in each iteration, it reads the next line.
It looks like each line is supposed to represent a key-value pair. The regex assumes that the key is not an empty string, and that the key and the value are separated by exactly five spaces, and the the value consists of exactly thirty-two letters. Each key-value pair is printed (perhaps for monitoring the progress), and is stored in oldfile_hash, which is most likely a hash.
So the point of using .gets is to tell when the file is finished being read. Essentially, it's tied to the
while (condition)
....
end
block. So gets serves as a little method that will keep giving ruby the next line of the file until there is no more lines to give.

Post issue with sinatra

Following this tutorial to create the route for the POST:
post '/secret' do
params[:secret].reverse
end
When I view this on the local server I get my secret message in reverse. But if I want to print another line, below the reverse line, the output gets all messed up on the localhost:9393.
post '/secret' do
p params[:secret].reverse
p params[:secret].reverse
end
Any ideas why, in the second block of code, only one line of the reversed secret shows up on my output after inputting the secret in the form on the main page? I'm looking to write more complex code but it seems like it's only printing the last line. Is this a Sinatra thing?
In your first example you're seeing your secret in reverse because Sinatra is handed the reversed string from the block and displays it.
In your second bit of code you're printing the reversed strings to the local output, which is where you'd expect to see the logs displayed. You're seeing a messed up string because the result of p params[:secret].reverse is not something Sinatra apparently wants to display correctly. Sinatra will fall back to trying to display the value returned from a route block if no other output had already been built up.
The next section of the tutorial you're following covers Views and Templates. Those are what you'll use to output a webpage.
It's just how Sinatra works. The return value of the post block is sent as response. The return value of the block is always the return value of the last statement inside the block. So your p is actually useless, it will only print the secret to the log. It just happens that p returns the value it was passed after printing it, so you still see one line because that is the return value of the block. If you actually want to return a response that contains the line twice, you have to build a single string that contains two lines. There are many ways to do this, here are some:
# use string interpolation to create a string that
# contains reversed_secret, followed by a newline,
# then again followed by reversed_secret
post '/secret' do
reversed_secret = params[:secret].reverse
"#{reversed_secret}\n#{reversed_secret}"
end
# use an array and join the values with a newline
post '/secret' do
reversed_secret = params[:secret].reverse
[reversed_secret, reversed_secret].join("\n")
end
# "print" individual lines to a StringIO object
# and read the resulting string afterwards
post '/secret' do
result = StringIO.new
reversed_secret = params[:secret].reverse
result.puts reversed_secret
result.puts reversed_secret
result.string
end
Whatever works best for you.
Oh, I see. You're using p.
Unlike PHP, Sinatra does not capture standard output. Rather, what is returned as the content .of the page is what is returned from the function.
In the first example, you return the result of reverse.
In the first example, you return nil, which is the result of the second p call.
If you want to return both reverses, you need to construct a string that contains them both:
post '/secret' do
"#{params[:secret].reverse}\n#{params[:secret].reverse}"
end

Parse huge file (10+gb) and write content in another one

I'm trying to use Sphinx Search Server to index a really huge file (around 14gb).
The file is whitespace separated, one entry per line.
To be able to use it with Sphinx, I need to provide a xml file to the Sphinx server.
How can I do it without killing my computer ?
What is the best strategy? Should I try to split the main file in several little files? What's the best way to do it?
Note: I'm doing it in Ruby, but I'm totally open to other hints.
Thanks for your time.
I think the main idea would be to parse the main file line by line, while generating a result XML. And every time it gets large enough, to feed it to Sphinx. Rinse and repeat.
What parsing do you need to do? If the transformations are restricted to just one line in the input at once and not too complicated, I would use awk instead of Ruby...
I hate guys who doesn't write solution after a question. So I'll try to don't be one of them, hopefully it will help somebody.
I added a simple reader method to the File class then used it to loop on the file based on a chunk size of my choice. Quite simple actually, working like a charm with Sphinx.
class File
# New static method
def self.seq_read(file_path,chunk_size=nil)
open(file_path,"rb") do |f|
f.each_chunk(chunk_size) do |chunk|
yield chunk
end
end
end
# New instance method
def each_chunk(chunk_size=1.kilobyte)
yield read(chunk_size) until eof?
end
end
Then just use it like this:
source_path = "./my_very_big_file.txt"
CHUNK_SIZE = 10.megabytes
File.seq_read(source_path, CHUNK_SIZE) do |chunk|
chunk.each_line do |line|
...
end
end

Ruby self-editing source code

I am creating a grammar corrector app. You input slang and it returns a formal English correction. All the slang words that are supported are kept inside arrays. I created a method that looks like this for when a slang is entered that is not supported.
def addtodic(lingo)
print"\nCorrection not supported. Please type a synonym to add '#{lingo}' the dictionary: "
syn = gets.chomp
if $hello.include?("#{syn}")
$hello.unshift(lingo)
puts"\nCorrection: Hello.\n"
elsif $howru.include?("#{syn}")
$howru.unshift(lingo)
puts"\nCorrection: Hello. How are you?\n"
end
end
This works, but only until the application is closed. how can I make this persist so that it amends the source code as well? If I cannot, how would I go about creating an external file that holds all of the cases and referencing that in my source code?
You will want to load and store your arrays in a external file.
How to store arrays in a file in ruby? is relevant to what you are trying to do.
Short example
Suppose you have a file that has one slang phrase per line
% cat hello.txt
hi
hey
yo dawg
The following script will read the file into an array, add a term, then write the array to a file again.
# Read the file ($/ is record separator)
$hello = File.read('hello.txt').split $/
# Add a term
$hello.unshift 'hallo'
# Write file back to original location
open('hello.txt', 'w') { |f| f.puts $hello.join $/ }
The file will now contain an extra line with the term you just added.
% cat hello.txt
hallo
hi
hey
yo dawg
This is just one simple way of storing an array to file. Check the link at the beginning of this answer for other ways (which will work better for less trivial examples).

Resources