For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > February 2007 > Help with search and replace









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Help with search and replace
Deepu

2007-02-23, 7:07 pm

Hi All,

I am trying to replace a word in a line with a different word.

Example:

File1:
THIS IS AN ERROR TEST
THIS IS A TEST
THIS IS NOT A TEST

I need to go through this file and check for ERROR in any line and
replace with FAIL.

Please help me on this.

Code:

#!/usr/local/bin/perl

$testFile = "File1";

open (FH, "$testFile") || die;

while (<FH> ) {
chomp;
if ($_ =~ /ERROR/) {
print "$_\n"; ## I get the line with ERROR here
}
}

Thanks

J. Gleixner

2007-02-23, 7:07 pm

Deepu wrote:
> Hi All,
>
> I am trying to replace a word in a line with a different word.
>
> Example:
>
> File1:
> THIS IS AN ERROR TEST
> THIS IS A TEST
> THIS IS NOT A TEST
>
> I need to go through this file and check for ERROR in any line and
> replace with FAIL.
>
> Please help me on this.
>
> Code:
>
> #!/usr/local/bin/perl
>
> $testFile = "File1";
>
> open (FH, "$testFile") || die;

Include why.
open( my $fh, '<', $testFile ) or die "Can't open $testFile: $!";

>
> while (<FH> ) {

while( <$fh> ) {
> chomp;

That's probably not needed.
> if ($_ =~ /ERROR/) {

if( /ERROR/ ) {
> print "$_\n"; ## I get the line with ERROR here

s/ERROR/FAIL/g;
print;
> }
> }

close $fh;

That will print the line, that used to contain ERROR,
and now contains FAIL, to STDOUT.

If you want to change it in the file.

perldoc -q 'How do I change one line'

How do I change one line in a file/delete a line in a file/insert a
line in the middle of a file/append to the beginning of a file?

Use the Tie::File module, which is included in the standard
distribution since Perl 5.8.0.

For information on how to use that module:

perldoc Tie::File

Deepu

2007-02-23, 7:07 pm

Thanks for the reply..how can i pass search & replace strings as
arguments to the script

Brian McCauley

2007-02-23, 7:07 pm

On Feb 23, 5:51 pm, "Deepu" <pradeep...@gmail.com> wrote without
adequate context:

[ please don't do that ]

> Thanks for the reply..how can i pass search & replace strings as
> arguments to the script


Command line arguments to a Perl script are placed in the special
array variable @ARGV.

Be aware, however, that in the solution given earlier in this thread
'ERROR' is being treated as a regular expression _not_ a plain string.

s/\Q$ARGV[0]/$ARGV[1]/g;

Or slightly more long winded but maybe clearer:

# Ouside the loop
my ($search,$replace) = @ARGV;

# Inside the loop
s/\Q$search/$replace/g;


Jürgen Exner

2007-02-23, 7:07 pm

Deepu wrote:
> Thanks for the reply..


What reply? I don't see any. What are you talking about?

> how can i pass search & replace strings as
> arguments to the script


The same way as you would pass any other argument to any other program: you
just type them on the command line after the command or script name.

jue


Deepu

2007-02-23, 7:07 pm

> > Thanks for the reply..
> What reply? I don't see any. What are you talking about?
>

I will try to post the message correctly in future..sorry about that

I tried the code as given below:

#!/usr/local/bin/perl

my ($search,$replace) = @ARGV;

my $baseDir = "/user/bin";

opendir (DIR, $baseDir) || die "Can't open $baseDir - $!\n";

# -- Perform the operation for each DIR
foreach my $simdir (readdir DIR) {

# -- If it is a directory and ends with 1-6
if (-d "$baseDir/$subdir" && $subdir =~ /(1|2|3|4|5|6)$/) {

# -- If the directory has subdirectories do the following operation
opendir (SUBDIR, "$baseDir"."/$subdir" ) || die "Can't open
$subdir - $!\n";

# -- Perform the operation for each of the sub-subdirectory
while ( my $subsubdir = readdir (SUBDIR)) {
if (-d "$baseDir/$subdir/$subsubdir" && $subsubdir =~ /(\d)$/) {
chomp $subsubdir;
if (-e "$baseDir/$subdir/$subsubdir/run.log")
{
my $temp = "$baseDir"."/$subdir/$subsubdir/File.log";
open (my $fh,'>',$temp) || die "Can't open $temp -$!\n";

while (<$fh> ){
s/$search/$replace/g;
}
close ($fh);
}
}
}
close SUBDIR;

# -- Else perform the same operation as before without the sub-
subdirectory
if (-e "$baseDir/$subdir/run.log")
{
my $temp = "$baseDir"."/$subdir/File.log";
open (my $fh,'>',$temp) || die "Can't open $temp -$!\n";

while (<$fh> ){
s/$search/$replace/g;
}
close ($fh);
}
}
}

close DIR;


But when i use this File.log becomes an empty file.

Basically File.log is present in $baseDir/subdir/ or $baseDir/$subdir/
$subsubdir

Example:

under /user/bin/ there are:

DIR1 - File.log
DIR2 - SUBDIR1 - File.log
DIR3 - SUBDIR1 - File.log
- SUBDIR2 - File.log
DIR4 - SUBDIR1 - File.log

File.log has:
THIS IS AN ERROR TEST
THIS IS A TEST
THIS IS NOT A TEST
THIS IS AN ERROR

I need to replace ERROR with FAIL or sometimes someother word so am
trying to pass as arguments



John W. Krahn

2007-02-23, 7:07 pm

Deepu wrote:
> I will try to post the message correctly in future..sorry about that
>
> I tried the code as given below:
>
> #!/usr/local/bin/perl


Missing:

use warnings;
use strict;

> my ($search,$replace) = @ARGV;
>
> my $baseDir = "/user/bin";
>
> opendir (DIR, $baseDir) || die "Can't open $baseDir - $!\n";
>
> # -- Perform the operation for each DIR
> foreach my $simdir (readdir DIR) {

^^^^^^^
You variable should be named $subdir, at least that is the name you are using
everywhere else in this program.


> # -- If it is a directory and ends with 1-6
> if (-d "$baseDir/$subdir" && $subdir =~ /(1|2|3|4|5|6)$/) {


You don't need capturing parentheses and a character class would be more
efficient:

if (-d "$baseDir/$subdir" && $subdir =~ /[123456]$/) {


> # -- If the directory has subdirectories do the following operation
> opendir (SUBDIR, "$baseDir"."/$subdir" ) || die "Can't open
> $subdir - $!\n";
>
> # -- Perform the operation for each of the sub-subdirectory
> while ( my $subsubdir = readdir (SUBDIR)) {
> if (-d "$baseDir/$subdir/$subsubdir" && $subsubdir =~ /(\d)$/) {
> chomp $subsubdir;
> if (-e "$baseDir/$subdir/$subsubdir/run.log")
> {
> my $temp = "$baseDir"."/$subdir/$subsubdir/File.log";
> open (my $fh,'>',$temp) || die "Can't open $temp -$!\n";
>
> while (<$fh> ){


You are trying to READ from a file opened WRITEONLY. This will not work.


> s/$search/$replace/g;


You are trying to modify the line in memory however this has no effect on the
file itself because you are not storing the line antwhere.


> }
> close ($fh);
> }
> }
> }
> close SUBDIR;
>
> # -- Else perform the same operation as before without the sub-
> subdirectory
> if (-e "$baseDir/$subdir/run.log")
> {
> my $temp = "$baseDir"."/$subdir/File.log";
> open (my $fh,'>',$temp) || die "Can't open $temp -$!\n";
>
> while (<$fh> ){
> s/$search/$replace/g;
> }
> close ($fh);
> }
> }
> }
>
> close DIR;
>
>
> But when i use this File.log becomes an empty file.
>
> Basically File.log is present in $baseDir/subdir/ or $baseDir/$subdir/
> $subsubdir
>
> Example:
>
> under /user/bin/ there are:
>
> DIR1 - File.log
> DIR2 - SUBDIR1 - File.log
> DIR3 - SUBDIR1 - File.log
> - SUBDIR2 - File.log
> DIR4 - SUBDIR1 - File.log
>
> File.log has:
> THIS IS AN ERROR TEST
> THIS IS A TEST
> THIS IS NOT A TEST
> THIS IS AN ERROR
>
> I need to replace ERROR with FAIL or sometimes someother word so am
> trying to pass as arguments


Something like this should work (UNTESTED):

#!/usr/local/bin/perl
use warnings;
use strict;
use File::Basename;

my ( $search, $replace ) = @ARGV;

my @files = (
glob( "/user/bin/*/run.log" ),
glob( "/user/bin/*[123456]/*/run.log" ),
);

for my $file ( @files ) {
my $new = dirname( $file ) . '/File.log';
open my $in, '<', $file or die "Cannot open '$file' $!";
open my $out, '>', $new or die "Cannot open '$new' $!";
while ( <$in> ) {
s/\Q$search\E/$replace/g;
print $out;
}
}

__END__





John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
Deepu

2007-02-23, 7:07 pm

> Something like this should work (UNTESTED):
>
> #!/usr/local/bin/perl
> use warnings;
> use strict;
> use File::Basename;
>
> my ( $search, $replace ) = @ARGV;
>
> my @files = (
> glob( "/user/bin/*/run.log" ),
> glob( "/user/bin/*[123456]/*/run.log" ),
> );
>
> for my $file ( @files ) {
> my $new = dirname( $file ) . '/File.log';
> open my $in, '<', $file or die "Cannot open '$file' $!";


How can i try to read and write to the same file?

> open my $out, '>', $new or die "Cannot open '$new' $!";
> while ( <$in> ) {
> s/\Q$search\E/$replace/g;
> print $out;
> }
> }
>
> __END__
>


J. Gleixner

2007-02-23, 7:07 pm

Deepu wrote:
Ahhh. who wrote this reply? Leave that in place.[color=darkred]
>
> How can i try to read and write to the same file?


Tie::File

or write to the new file and rename it to the old.

perldoc -f rename

or use File::Copy or possibly something on
the command line like:

perl -pi -e 's/search/replace/g' /user/bin/*/run.log
/user/bin/*[123456]/*/run.log

or many more...

Be sure to use a test directory and files, before you
start trashing actual files.

You can find many examples on-line. Give that a try
or try to figure it out by reading the various FAQs,
before simply replying with another question.
Jürgen Exner

2007-02-23, 10:04 pm

Deepu wrote:
> my $temp = "$baseDir"."/$subdir/$subsubdir/File.log";
> open (my $fh,'>',$temp) || die "Can't open $temp -$!\n";


Ok, you are opening the file

> while (<$fh> ){


You are reading each line in the file into $_

> s/$search/$replace/g;


You are replacing something in $_ with something else

> }


And then throwing it away

> close ($fh);


> But when i use this File.log becomes an empty file.


Well, you never ever write anything anywhere.

jue

jue


Tad McClellan

2007-02-23, 10:04 pm

Deepu <pradeep.bg@gmail.com> wrote:

> How can i try to read and write to the same file?



You can try any way that you want to.

Very few of them will work though.


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Tad McClellan

2007-02-23, 10:04 pm

Deepu <pradeep.bg@gmail.com> wrote:

> while ( my $subsubdir = readdir (SUBDIR)) {
> if (-d "$baseDir/$subdir/$subsubdir" && $subsubdir =~ /(\d)$/) {
> chomp $subsubdir;



Do you really have directories whose names end with a newline?


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
John W. Krahn

2007-02-24, 4:07 am

Deepu wrote:
>
> How can i try to read and write to the same file?


Something like this should work (UNTESTED):

#!/usr/local/bin/perl
use warnings;
use strict;

my ( $search, $replace ) = @ARGV;

@ARGV = (
glob( "/user/bin/*[0-9]/run.log" ),
glob( "/user/bin/*[1-6]/*[0-9]/run.log" ),
);

$^I = '';

while ( <> ) {
s/\Q$search\E/$replace/g;
print;
}

__END__




John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
Ayaz Ahmed Khan

2007-02-24, 4:08 am

"Deepu" typed:

> Hi All,
> I am trying to replace a word in a line with a different word.
> I need to go through this file and check for ERROR in any line and
> replace with FAIL.


A one-liner would do:

$ perl -p -i -e 's/\bERROR\b/FAIL/g' file

--
Ayaz Ahmed Khan

A witty saying proves nothing, but saying something pointless gets
people's attention.

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com