f



Editing a text file and then replacing existing file

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

-- 
Posted via http://www.ruby-forum.com/.

0
Bob
2/2/2011 3:53:46 PM
comp.lang.ruby 48886 articles. 0 followers. Post Follow

2 Replies
746 Views

Similar Articles

[PageSpeed] 16

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)

-Jeremy

0
Jeremy
2/2/2011 4:31:10 PM
On Wed, Feb 2, 2011 at 5:31 PM, Jeremy Bopp <jeremy@bopp.net> 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=3D'c:\ruby192\my_projects\IIS_Logs\ex11012607.log'
>> search_text =3D %r{/memberinfo/downline/tree/can.asp}
>> search_text2 =3D %r{/memberinfo/downline/tree/disto.asp}
>> search_text3 =3D %r{/styles/default.css}
>> search_text4 =3D %r{/scripts/generalscript.js}
>> search_text5 =3D %r{/memberinfo/downline/tree/upl.asp}
>> search_text6 =3D %r{/scripts/wz_jsgraphics.js}
>> search_text7 =3D %r{/memberinfo/downline/tree/disfo2.asp}
>> search_text8 =3D %r{/styles/png.htc}
>> File.open(path, 'a+') do |file|
>> =A0 file.each_line do |line|
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text ||
>> =A0 puts(line) unless line =3D~ search_text2 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text3 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text4 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text5 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text6 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text7 ||
>> =A0 =A0 =A0 puts(line) unless line =3D~ search_text8
>> =A0 =A0end
>> 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. =A0This uses the x option for the regex=
p
> construction so that the format is a little more legible:
>
> search_text =3D %r{
> =A0/memberinfo/downline/tree/can.asp =A0 =A0|
> =A0/memberinfo/downline/tree/disto.asp =A0|
> =A0/styles/default.css =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0|
> =A0/scripts/generalscript.js =A0 =A0 =A0 =A0 =A0 =A0|
> =A0/memberinfo/downline/tree/upl.asp =A0 =A0|
> =A0/scripts/wz_jsgraphics.js =A0 =A0 =A0 =A0 =A0 =A0|
> =A0/memberinfo/downline/tree/disfo2.asp |
> =A0/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. =A0Alarm bells should go off in your head if
> you see that sort of thing. =A0More importantly though, you need to take =
a
> closer look at what you're doing there with the || operator. =A0That's no=
t
> exactly doing what you seem to intend. ;-)
>
> Now we get to the meat of your problem. =A0You 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. =A0It'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|
> =A0File.open(temp_path, "w") do |outfile|
> =A0 =A0infile.each_line do |line|
> =A0 =A0 =A0outfile.write(line) unless line =3D~ search_text
> =A0 =A0end
> =A0end
> 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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

0
Robert
2/2/2011 4:52:41 PM
Reply: