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.
···
On Wed, May 04, 2005 at 09:08:19PM +0900, Ralf Müller wrote:
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
# 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
···
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:
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).
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"
Great.
At last i can get rid of these perl one-liners.
best regards
ralf
···
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.
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.