Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

replace text

by dawg31wh (Initiate)
on Jul 11, 2013 at 15:22 UTC ( [id://1043758]=perlquestion: print w/replies, xml ) Need Help??

dawg31wh has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to make a program that will search files and replace text with user interaction. It looks like everything works fine, but when I cat the file it still has the original text. Any guidance on how to fix?

use warnings; use strict; while (1) { system("clear"); print "Enter P to process a file or Q to quit: "; chomp( my $ans=<STDIN> ); if ( $ans =~ /^p$/i ) { print "What file would you look to open? "; chomp( my $file=<STDIN> ); next if !-e $file; open(my $fh, '<', $file) or die "Could not open file: $!"; print "What text would you like to search for? "; chomp( my $find=<STDIN> ); print "What text would you like it replaced with? "; chomp( my $replace=<STDIN> ); while ( my $line=<$fh> ) { if ( $line =~ /$find/i ) { $line =~ s/\b$find\b/$replace/g; } print $line; } next; } elsif ( $ans =~ /^q$/ ) { exit; } else { next; } }

Replies are listed 'Best First'.
Re: replace text
by muba (Priest) on Jul 11, 2013 at 15:30 UTC
    use warnings; # Great :) use strict; # Also great :) ... # Ok, so here you open the file for INPUT. Great :) open(my $fh, '<', $file) or die "Could not open file: $!"; ... # Ok, so here you show the line to the user, mutatis mutan +dis. print $line; ... # But where did you open the file for OUTPUT? # And where did you write the line (changed when applicable) to + the file? # This code is unnecessary. else { next; } }
Re: replace text
by mtmcc (Hermit) on Jul 11, 2013 at 16:54 UTC
    One or two suggestions:

    #!/usr/bin/perl use warnings; use strict; my $found = 0; my $line = 0; while (1) { system("clear"); print "Enter P to process a file or Q to quit: "; chomp( my $ans=<STDIN> ); if ( $ans =~ /^p$/i ) { print "What file would you look to open? "; chomp( my $file=<STDIN> ); die "Could not open file: $file!\n\n" if !-e $file; open(my $fh, '<', $file); print "What text would you like to search for? "; chomp( my $find=<STDIN> ); print "What text would you like it replaced with? "; chomp( my $replace=<STDIN> ); open (NEW, ">", "new.txt"); while ( <$fh> ) { if ($_ =~ /$find/i ) { $line = $_; $line =~ s/$find/$replace/g; print NEW "$line"; $found += 1; } else { print NEW "$_"; } } print STDERR "\nFound and replaced $found copies of \"$find\" +with \"$replace\".\n" if $found > 0; print STDERR "\n$found copies of \"$find\" found in $file.\n" +if $found == 0; unlink "new.txt" if $found == 0; sleep (5); } elsif ( $ans =~ /^Q$/ ) { exit(); } close NEW; $found = 0; }

    Michael

      Michael Thanks your suggestions work.

        Glad to be able to help.

        By the way, if you really want to replace the original file with the new changes, you could push the new lines to an array, close the input file, and write over it with the new array, maybe something like this:

        #!/usr/bin/perl use warnings; use strict; my $found = 0; my $line = 0; my @newFile = (); while (1) { system("clear"); print "Enter P to process a file or Q to quit: "; chomp( my $ans=<STDIN> ); if ( $ans =~ /^p$/i ) { print "What file would you look to open? "; chomp( my $file=<STDIN> ); die "Could not open file: $file!\n\n" if !-e $file; open(my $fh, '<', $file); print "What text would you like to search for? "; chomp( my $find=<STDIN> ); print "What text would you like it replaced with? "; chomp( my $replace=<STDIN> ); #open (NEW, ">", "new.txt"); while ( <$fh> ) { if ($_ =~ /$find/i ) { $line = $_; $line =~ s/$find/$replace/g; push(@newFile,"$line"); $found += 1; } else { push(@newFile, "$_"); } } open (WIPEORIGINAL, ">", "$file"); for (@newFile) { print WIPEORIGINAL "$_"; } close WIPEORIGINAL; print STDERR "\nFound and replaced $found copies of \"$find\" +with \"$replace\".\n" if $found > 0; print STDERR "\n$found copies of \"$find\" found in $file.\n" +if $found == 0; @newFile = (); $found = 0; sleep (5); } elsif ( $ans =~ /^Q$/ ) { exit(); } # close NEW; }

        --Michael

Re: replace text
by Eily (Monsignor) on Jul 11, 2013 at 15:52 UTC

    You should quotemeta your $find string, to be sure that the search pattern is taken literally. For example searching for "a cat (or a dog)" will match "a cat or a dog" without the parenthesis.

Re: replace text
by marinersk (Priest) on Jul 11, 2013 at 21:57 UTC

    Summary of problem: You are never writing the data out to a file.

    You read it from file.
    You change it in scalar (memory).
    You print to console.

    Missing is the step to write it to an output file.

    As noted by others, one approach is slurp-digest-spew (open, read to array, close, modify array, open for write, write, close. It is probably more efficient to perform the modifications as you read the data, which your script already does. This has the cost of increased risk of file corruption if power goes out during the spew phase, and it consumes more memory for the array. It has the advantage of being easy to write, and less disk space consumed.

    Another approach is to write a temporary output file. open input, open output, read-process-write loop, close, close, rename or unlink input file (make sure rename works if you use that!), rename output file to input file. This has the advantage of reduced vulnerability to file corruption due to power failure at the cost of increased disk consumption. It does use less memory, as there is no array involved.

    But the reason the file is unchanged when you cat it is because you didn't change it in your script. You only write the modified data to the screen.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1043758]
Approved by muba
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2024-04-19 04:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found