writing to a file with gsub!

R

Ralf Müller

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
 
J

Joost Diepenmaat

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.
 
S

Stefan Lang

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
 
R

Ralf Müller

# 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
 
R

Robert Klemme

Ralf said:
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
 
F

Friday

Robert said:
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).
 
R

Ralf Müller

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
 
J

James Edward Gray II

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
 
R

Ralf Müller

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
 
J

Joost Diepenmaat

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 :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,792
Messages
2,569,639
Members
45,353
Latest member
RogerDoger

Latest Threads

Top