Mr Mojo wrote:

I have a text file (texst1.txt) that reads:

The quick brown fox jumped over the lazy dog.

I would like to replace the word fox with coyote.
Is there an easier/simpler/cooler way to do this?

You can run this from the command line:


perl -pi -es/fox/coyote/g test1.txt

Or if you want to have a backup in test1.txt~:

perl -pi~ -es/fox/coyote/g test1.txt

or in test1.txt.bak:

perl -pi.bak -es/fox/coyote/g test1.txt

See perldoc perlrun for the command line switches.
If you want to save this script in a file, write:

#!/usr/bin/perl -pi~
s/fox/coyote/g;

and run it with your file as an argument:

./script test1.txt

As for your program, I might have few suggestions:

#!/usr/bin/perl -w
use strict;

You might prefer "use warnings" instead of -w for better control of warnings. See: perldoc perllexwarn


open (FILE, "test1.txt");
open (NEWFILE, ">>tmp");

Always add at least 'or die $!' when you are opening files, because it can fail for many reasons:


open FILE, "test1.txt" or die "Error opening test1.txt: $!\n";
open NEWFILE, ">>tmp" or die "Error opening tmp: $!\n";

You probably want '>' instead of '>>' here. If there already is a file named 'tmp' opening it with '>>' will append new lines at the end, while '>' will truncate it first.

See: perldoc perlopentut

If you don't want to add "or die" to every command which can fail, you may write something like this instead:

use Fatal qw(open close unlink rename);

at the beginning of your program.

while (<FILE>) {
    if ($_ =~ /fox/) {
        s/fox/coyote/;
    }
    print NEWFILE $_;
}

The "if ($_ =~ /fox/)" is redundant, because s/fox/coyote/ will change only lines with "fox" anyway. s/fox/coyote/ will only change the first "fox" in every line. Use s/fox/coyote/g to change every one if there are more foxes in any single line. $_ is default for print. So the above is equivalent to:


while (<FILE>) {
    s/fox/coyote/;
    print NEWFILE;
}

close FILE;
close NEWFILE;
unlink "test1.txt";
rename "tmp", "test1.txt";

You might also check the return values of unlink and rename to "die" if they fail:


unlink "test1.txt" or die "Unlinking test1.txt: $!\n";
rename "tmp", "test1.txt" or die "Renamimg tmp: $!\n";

or at least:

unlink "test1.txt" or die $!;
rename "tmp", "test1.txt" or die $!;

Or you can use the trick with "use Fatal" instead.

In the examples I showed above you always had to give file name as an argument, while the file name is hardcoded into your program. To have exactly the same functionality, you might write this program:

#!/usr/bin/perl -wpi
BEGIN [EMAIL PROTECTED] = 'test1.txt'}
s/fox/coyote/g;

It does the same as yours with only few exceptions: it prints an error when it can't open the file:

Can't open test1.txt: No such file or directory.

It changes every "fox" to "coyote" and not only the first one in a line (thanks to the "g" at the end of substitution, see: perldoc perlre) and it won't include any old "tmp" file if there is any.

The above program even if cool (for some definition of coolness) may be quite hard to understand at first, so if you have any questions I can explain it in more details.

--
ZSDC Perl and Systems Security Consulting


-- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>




Reply via email to