making replacements in a file

J

Jeff Thies

I have a file that I need to make some substitutions in:

open FH, "my_file" or die "Can't open... $!";

@file=<FH>;

Can I read the file handle so it is a scalar and I can just do this?:

$file=~s/replace_me/with_this/gis; # small files

and then print back to a filehandle.

Or should I do something like this:

my @new_file=();
while(<FH>){
$_=~s/replace_me/with_this/gi;
push @new_file, $_;
}

and then print @new_file to a filehandle? Or would that be a reference
to @new_file?

Seems like there should be a better way than any of these.

Jeff
 
B

Bob Walton

Jeff said:
I have a file that I need to make some substitutions in:

open FH, "my_file" or die "Can't open... $!";

@file=<FH>;

Can I read the file handle so it is a scalar and I can just do this?:


Sure. Slurp it. Set the value of $/ to undef, perhaps like:

{local $/; #make $/ undef only for the duration of this block,
#so it doesn't screw up possible subsequent reads.
$file=<FH>; #slurp entire file to scalar.
}

This sets the input record separator string to undef, which is a special
case that causes file "slurping". See:

perldoc perlvar

for more info.

$file=~s/replace_me/with_this/gis; # small files

and then print back to a filehandle.

Or should I do something like this:

my @new_file=();
while(<FH>){
$_=~s/replace_me/with_this/gi;
push @new_file, $_;
}

and then print @new_file to a filehandle? Or would that be a reference
to @new_file?


That, of course, would also work, unless the "replace_me" string
contains stuff which is supposed to match over a newline. The fact that
you included the "s" regexp modifier in your previous "slurp version"
regexp indicates that perhaps you intended for that to be the case
(otherwise, "s" would serve no purpose).

Of course, you don't really have to push all the lines out to an array
in the above -- just write out the modified lines as you read them.
That gives your program the distinct advantage of being able to process
a gigabyte file on your old 386 with 16 Mb of memory. Just replace the
push line with something like:

print OUT $_;

and place something like:

open OUT,">output.file" or die "Oops, $!";

before the while loop.

Seems like there should be a better way than any of these.


There's always more than one way to do it. Which is "better" depends on
a lot of stuff you haven't defined for us, as well as your opinion of
what "better" means.
 
M

Mina Naguib

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jeff said:
I have a file that I need to make some substitutions in:

open FH, "my_file" or die "Can't open... $!";

@file=<FH>;

Can I read the file handle so it is a scalar and I can just do this?:

$file=~s/replace_me/with_this/gis; # small files

and then print back to a filehandle.

Or should I do something like this:

my @new_file=();
while(<FH>){
$_=~s/replace_me/with_this/gi;
push @new_file, $_;
}

and then print @new_file to a filehandle? Or would that be a reference
to @new_file?

You can let perl worry about opening the files, writing back to them, and even looping over the
lines, through command-line switches. This program does what you're doing above:

- -- cut here --
#!/usr/bin/perl -pi

s/replace_me/with_this/gi;
- -- cut here --

That's it ! For more info on the -p and the -i switches (and many other interesting ones), see
perldoc perlrun


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE/DkOteS99pGMif6wRAvrYAKD/oylKq/WL6pLBixWlA9VCng542QCfY/dt
BbWHBtt+1GK7PCGVriMaMuA=
=6jHE
-----END PGP SIGNATURE-----
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top