[newbie] in place file editing and ! meaning

X

Xavier Hanin

Hi all,

I'm brand new to ruby, and I'm looking for a way to open a file, read
its content and modify it. I've seen that I can open a file in read
write mode, but I can't figure out how it works. If I want to replace
all occurences of 'search' by 'replace', for instance, what do I have to
do?

Searching for an answer to this question, I've found scripts using gsub!
What is this exclamation mark?

Thanks in advance for your help!

Xavier
 
L

Logan Capaldo

Hi all,

I'm brand new to ruby, and I'm looking for a way to open a file, read
its content and modify it. I've seen that I can open a file in read
write mode, but I can't figure out how it works. If I want to replace
all occurences of 'search' by 'replace', for instance, what do I
have to
do?

Searching for an answer to this question, I've found scripts using
gsub!
What is this exclamation mark?

Thanks in advance for your help!

Xavier

The ! (pronounced bang usually) means that a method is a "dangerous"
version of a method with the same name. In this particular case it
means that it's the inplace version of gsub (global substitution).
 
M

Morton Goldberg

I take it you are referring to ruby code such as:

FOLDER = "#{ENV['HOME']}/Desktop/" # or whatever folder you want
INFILE = "input.txt"
OUTFILE = "output.txt"

old = File.read(FOLDER + INFILE) # read file in as one big string
old.gsub!(/\bsearch\b/, "replace") # do in-place substitution
File.open(FOLDER + OUTFILE, "w") {|new| new.write(old)} # write
modified text out to disk.

This code does not open "input.txt" in RW mode nor modify it in
place. For one thing, gsub! only works on strings not file objects.
For another, I'm too nervous to do that kind of thing. Of course, if
INFILE == OUTFILE, it would overwrite "input.txt".

In general, it is a naming convention that a method ending in !
signifies that the method does in-place (destructive) modification to
the receiver. I first ran into this convention when studying scheme
back in the 1980s. I don't know if has any history beyond that.
Schemers would read gsub! as GEE-SUB-BANG. I'm new to ruby, too, so
I'm not sure if rubyists read it the same way.

Regards, Morton
 
X

Xavier Hanin

Logan said:
The ! (pronounced bang usually) means that a method is a "dangerous"
version of a method with the same name. In this particular case it
means that it's the inplace version of gsub (global substitution).

OK, thanks for the information and the pronounciation tip.

But I still don't know how to edit a file while reading it. I've made
further googling on the subject, and the only solutions I find are:
- "read all, manipulate, write all", which doesn't seem very good with
huge files
- use -i options with ruby command line, but this seems to work only
with files passed on the command line, which isn't my case.

So, could somebody tell me if it's possible to update a file in ruby
(except these two solutions)?
 
E

Elliot Temple

OK, thanks for the information and the pronounciation tip.

But I still don't know how to edit a file while reading it. I've made
further googling on the subject, and the only solutions I find are:
- "read all, manipulate, write all", which doesn't seem very good with
huge files
- use -i options with ruby command line, but this seems to work only
with files passed on the command line, which isn't my case.

So, could somebody tell me if it's possible to update a file in ruby
(except these two solutions)?

do you want something like this?

cg5:~ >cat a
abcdefghijklm
cg5:~ >cat a.rb
f = File.new("a", "r+")
while f.read(1) !~ /d/
end
f.write("ZZZ")
cg5:~ >ruby a.rb
cg5:~ >cat a
abcdZZZhijklm
cg5:~ >


-- Elliot Temple
http://www.curi.us/blog/
 
D

Douglas McNaught

Xavier Hanin said:
I'm brand new to ruby, and I'm looking for a way to open a file, read
its content and modify it. I've seen that I can open a file in read
write mode, but I can't figure out how it works. If I want to replace
all occurences of 'search' by 'replace', for instance, what do I have to
do?

In general, you need to read in the file (usually line by line) and
write out a new copy with the changes you want. Editing in place is
only possible if the replacement string is exactly the same length as
the original.
Searching for an answer to this question, I've found scripts using gsub!
What is this exclamation mark?

It means it changes the object it operates on, rather than returning a
changed copy.

-Doug
 
L

Logan Capaldo

OK, thanks for the information and the pronounciation tip.

But I still don't know how to edit a file while reading it. I've made
further googling on the subject, and the only solutions I find are:
- "read all, manipulate, write all", which doesn't seem very good with
huge files
- use -i options with ruby command line, but this seems to work only
with files passed on the command line, which isn't my case.

So, could somebody tell me if it's possible to update a file in ruby
(except these two solutions)?

To do in place editing, basically you just do it. The problem is
doing it correctly. One way is to use fixed-size chunks:

CHUNK_SIZE = 1024
File.open("somefile", "r+") do |f|
loop do
pos = f.tell
s = f.read(CHUNK_SIZE)
break if s.nil? # We've read and transformed the file
s.gsub!(/a/, 'b')
f.seek(pos, IO::SEEK_SET)
f.write(s)
end
end

The problem with this method is if the substitued string is longer or
shorter than the read string it'll mess it up and you'll have to
shift the rest of the file around. Another way (and how I believe
ruby's command line switch -i works) is to write the modified version
to a temporary file, and then remove the original version, replacing
it with the modified version. A third, relatively idiot proof method
is to use the mmap extension. This is awesome, but is not gonna be
portable outside of a *nix. (And introduces another dependency).
 
M

Morton Goldberg

How big is huge? Nowadays, I think the "read all, manipulate, write
all" technique is probably the best for text files up to many megabytes.

Regards, Morton
 
X

Xavier Hanin

Many thanks all of you! What an incredibly active community ruby has,
I'm impressed. And the tell and seek methods are exactly what I was
looking for (even if I agree the read, manipulate, write is much easier
to write and can address most problems).

Thanks again, and I feel like I'll soon become a ruby afficionado :)
 
D

dblack

E

Elliot Temple

Hi --



In this case that's true, but in general, ! means a "dangerous" method
with a non-dangerous counterpart. (See Logan's answer.)

What are some examples of method names with ! used to indicate some
dangerous thing other than a destructive method?

-- Elliot Temple
http://www.curi.us/blog/
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top