From: Robert Klemme Date: 2011-02-03T01:52:41+09:00 Subject: Re: Editing a text file and then replacing existing file On Wed, Feb 2, 2011 at 5:31 PM, Jeremy Bopp wrote: > On 2/2/2011 9:53 AM, Bob Hatch wrote: >> I have a script that I use to find text in a file and then delete the >> line(s) the text is on. That part works. What I have been unsuccessfully >> trying to do is take the new text and overwrite the existing file that I >> did the search and delete on. Here is my existing code that finds the >> lines and deletes them: >> >> path='c:\ruby192\my_projects\IIS_Logs\ex11012607.log' >> search_text = %r{/memberinfo/downline/tree/can.asp} >> search_text2 = %r{/memberinfo/downline/tree/disto.asp} >> search_text3 = %r{/styles/default.css} >> search_text4 = %r{/scripts/generalscript.js} >> search_text5 = %r{/memberinfo/downline/tree/upl.asp} >> search_text6 = %r{/scripts/wz_jsgraphics.js} >> search_text7 = %r{/memberinfo/downline/tree/disfo2.asp} >> search_text8 = %r{/styles/png.htc} >> File.open(path, 'a+') do |file| >>   file.each_line do |line| >>       puts(line) unless line =~ search_text || >>   puts(line) unless line =~ search_text2 || >>       puts(line) unless line =~ search_text3 || >>       puts(line) unless line =~ search_text4 || >>       puts(line) unless line =~ search_text5 || >>       puts(line) unless line =~ search_text6 || >>       puts(line) unless line =~ search_text7 || >>       puts(line) unless line =~ search_text8 >>    end >> file.write(line) >> file.close >> end > > First of all, let's simplify this code by using a single regexp that > will match all lines of interest.  This uses the x option for the regexp > construction so that the format is a little more legible: > > search_text = %r{ >  /memberinfo/downline/tree/can.asp    | >  /memberinfo/downline/tree/disto.asp  | >  /styles/default.css                  | >  /scripts/generalscript.js            | >  /memberinfo/downline/tree/upl.asp    | >  /scripts/wz_jsgraphics.js            | >  /memberinfo/downline/tree/disfo2.asp | >  /styles/png.htc > }x > > Beware that the x option will cause any unescaped whitespace in your > regexp to be ignored, so you need to take care if you need to match a > file path that has spaces in it. > > With this regexp you would be able to use a single puts(line) call. > BTW, you should really try to avoid duplicated code like you have with > your puts lines in general.  Alarm bells should go off in your head if > you see that sort of thing.  More importantly though, you need to take a > closer look at what you're doing there with the || operator.  That's not > exactly doing what you seem to intend. ;-) > > Now we get to the meat of your problem.  You can't write to the file > from which you're reading without manually maintaining at least 2 > pointers into the file, one for your current read position and another > for your write position.  It's *much* easier actually create a new file > to hold the filtered data and then use that file to replace the original: > > File.open(source_path) do |infile| >  File.open(temp_path, "w") do |outfile| >    infile.each_line do |line| >      outfile.write(line) unless line =~ search_text >    end >  end > end > File.rename(temp_path, source_path) Just an additional perspective: for things like this it's probably easier to use GNU fgrep: $ fgrep -v -f search_texts input > output $ mv input input~ && mv output input Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/