[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

writing to a file with gsub!

Ralf Müller

5/4/2005 12:08:00 PM

Hi,

i simply want so change an existing file

ram@lilith:~/src/ruby$cat test
123 wer ---
245545 hzrzu ----
245 dfgdfh --


and i thought that

irb(main):012:0> file = File.open('test'); file.each do |line| line.gsub!(/\d+/,'###') end

would do this, because each iterates accross the file.
But nothing is changed.

Where are my mistakes??


Many Thanks
Ralf


11 Answers

Joost Diepenmaat

5/4/2005 12:29:00 PM

0

On Wed, May 04, 2005 at 09:08:19PM +0900, Ralf Müller wrote:
> Hi,
>
> i simply want so change an existing file
[ ... ]
> irb(main):012:0> file = File.open('test'); file.each do |line| line.gsub!(/\d+/,'###') end
>

AFAIK line is a String so changing it won't automatically change the
file. There's a reason, too:

Most operating systems do not support mixing reading and writing lines
to the same file, since most OS's do not handle lines as distinctive
records - i.e: changing the length of one line will generally mean
changing all the content from that point till the end of the file,
which is obviously very inefficient.

Generally, the best you can do is open a new file for writing, write
each line to the new file after changing it, and then rename/move the
new file name to the old filename.

Joost.



Stefan Lang

5/4/2005 1:04:00 PM

0

On Wednesday 04 May 2005 14:28, Joost Diepenmaat wrote:
> On Wed, May 04, 2005 at 09:08:19PM +0900, Ralf Müller wrote:
> > Hi,
> >
> > i simply want so change an existing file
>
> [ ... ]
>
> > irb(main):012:0> file = File.open('test'); file.each do |line|
> > line.gsub!(/\d+/,'###') end
>
> AFAIK line is a String so changing it won't automatically change the
> file. There's a reason, too:
[...]

# open file test for reading
open "test" do |src|
# open test.tmp for writing
open "test.tmp", "w" do |tmp|
# read line from test, substitute and write modified line to test.tmp
src.each { |line| tmp << line.gsub(/\d+/, '###') }
end
end
File.rename "test.tmp", "test"

Stefan



Ralf Müller

5/4/2005 1:10:00 PM

0

On Wed, 4 May 2005 22:03:30 +0900
Stefan Lang <langstefan@gmx.at> wrote:

> # open file test for reading
> open "test" do |src|
> # open test.tmp for writing
> open "test.tmp", "w" do |tmp|
> # read line from test, substitute and write modified line to test.tmp
> src.each { |line| tmp << line.gsub(/\d+/, '###') }
> end
> end
> File.rename "test.tmp", "test"
>
> Stefan
>

das haut!

Thanx !!!





ralf


Robert Klemme

5/4/2005 1:26:00 PM

0

Ralf Müller wrote:
> Hi,
>
> i simply want so change an existing file
>
> ram@lilith:~/src/ruby$cat test
> 123 wer ---
> 245545 hzrzu ----
> 245 dfgdfh --
>
>
> and i thought that
>
> irb(main):012:0> file = File.open('test'); file.each do |line|
> line.gsub!(/\d+/,'###') end
>
> would do this, because each iterates accross the file.
> But nothing is changed.
>
> Where are my mistakes??

As others have pointed out, reading and writing to the same file at a time
is quite complicated. Your approach could only work with memory mapped
files...

But it's simpler - as simple as

ruby -pi.bak -e 'gsub /\d+/, "###"' your_file

In case you wonder about the parameter's meanings:

15:23:01 [source]: ruby -h
Usage: ruby [switches] [--] [programfile] [arguments]
-0[octal] specify record separator (\0, if no argument)
-a autosplit mode with -n or -p (splits $_ into $F)
-c check syntax only
-Cdirectory cd to directory, before executing your script
-d set debugging flags (set $DEBUG to true)
-e 'command' one line of script. Several -e's allowed. Omit
[programfile]
-Fpattern split() pattern for autosplit (-a)
-i[extension] edit ARGV files in place (make backup if extension
supplied)
-Idirectory specify $LOAD_PATH directory (may be used more than
once)
-Kkcode specifies KANJI (Japanese) code-set
-l enable line ending processing
-n assume 'while gets(); ... end' loop around your script
-p assume loop like -n but print line also like sed
-rlibrary require the library, before executing your script
-s enable some switch parsing for switches after script
name
-S look for the script using PATH environment variable
-T[level] turn on tainting checks
-v print version number, then turn on verbose mode
-w turn warnings on for your script
-W[level] set warning level; 0=silence, 1=medium, 2=verbose
(default)
-x[directory] strip off text before #!ruby line and perhaps cd to
directory
--copyright print the copyright
--version print the version

15:24:54 [temp]: echo "asdasda123sdasdsd" > your_file
15:25:03 [temp]: cat your_file
asdasda123sdasdsd
15:25:11 [temp]: ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
15:25:15 [temp]: cat your_file
asdasda###sdasdsd
15:25:16 [temp]: cat your_file.bak
asdasda123sdasdsd

Kind regards

robert

Friday

5/4/2005 1:40:00 PM

0

Robert Klemme wrote:
> As others have pointed out, reading and writing to the same file at a time
> is quite complicated. Your approach could only work with memory mapped
> files...
>
> But it's simpler - as simple as
>
> ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
>

This belongs in a ruby one-liner hall of fame.

It is so practical and useful that it can be the perfect example to
dispell any myth about ruby requiring verbose oo syntax (to newcomers
reading about ruby being oo).

Ralf Müller

5/4/2005 1:59:00 PM

0

On Wed, 4 May 2005 22:30:07 +0900
"Robert Klemme" <bob.news@gmx.net> wrote:


> But it's simpler - as simple as
>
> ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
>

But what about using \1 and \n in the second argument of gsub. Doesn't require \1 single-quotes
and \n double quotes?

'\1'+"\n" will not work


James Gray

5/4/2005 2:06:00 PM

0

On May 4, 2005, at 8:59 AM, Ralf Müller wrote:

> On Wed, 4 May 2005 22:30:07 +0900
> "Robert Klemme" <bob.news@gmx.net> wrote:
>
>
>> But it's simpler - as simple as
>>
>> ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
>>
>
> But what about using \1 and \n in the second argument of gsub. Doesn't
> require \1 single-quotes
> and \n double quotes?

No. If you want to put \1 in double quotes, just add a backslash.
"\\1\n" works fine.

Hope that helps.

James Edward Gray II




Ralf Müller

5/4/2005 2:20:00 PM

0

On Wed, 4 May 2005 23:06:21 +0900
James Edward Gray II <james@grayproductions.net> wrote:

> On May 4, 2005, at 8:59 AM, Ralf Müller wrote:
>
> > On Wed, 4 May 2005 22:30:07 +0900
> > "Robert Klemme" <bob.news@gmx.net> wrote:
> >
> >
> >> But it's simpler - as simple as
> >>
> >> ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
> >>
> >
> > But what about using \1 and \n in the second argument of gsub. Doesn't
> > require \1 single-quotes
> > and \n double quotes?
>
> No. If you want to put \1 in double quotes, just add a backslash.
> "\\1\n" works fine.
>
> Hope that helps.
>

Great.
At last i can get rid of these perl one-liners.


best regards
ralf



Joost Diepenmaat

5/4/2005 2:28:00 PM

0

On Wed, May 04, 2005 at 11:20:21PM +0900, Ralf Müller wrote:
> On Wed, 4 May 2005 23:06:21 +0900
> James Edward Gray II <james@grayproductions.net> wrote:
>
> > On May 4, 2005, at 8:59 AM, Ralf Müller wrote:
> >
> > > On Wed, 4 May 2005 22:30:07 +0900
> > > "Robert Klemme" <bob.news@gmx.net> wrote:
> > >
> > >
> > >> But it's simpler - as simple as
> > >>
> > >> ruby -pi.bak -e 'gsub /\d+/, "###"' your_file
> > >>
> > >
> > > But what about using \1 and \n in the second argument of gsub. Doesn't
> > > require \1 single-quotes
> > > and \n double quotes?
> >
> > No. If you want to put \1 in double quotes, just add a backslash.
> > "\\1\n" works fine.
> >
> > Hope that helps.
> >
>
> Great.
> At last i can get rid of these perl one-liners.

You mean you prefer

ruby -pi.bak -e 'gsub /\d+/, "###"' your_file

over

perl -pi.bak -e 'gsub /\d+/, "###"' your_file

?

Yeah, I can clearly see the advantage :-)




James Gray

5/4/2005 2:33:00 PM

0

On May 4, 2005, at 9:28 AM, Joost Diepenmaat wrote:

> perl -pi.bak -e 'gsub /\d+/, "###"' your_file

perl -pi.bak -e 's/\d+/###/g' your_file

:)

James Edward Gray II