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

Howdy Monks!

I seem to be having some difficulty in chapter 9 of the Llama. To all those who have helped me out with the other chp 9 questions, a ton of thanks. To anyone kind enough to help out here, please understand that I am a novice struggling to ride the Llama, and I will likely not understand anything not already either a) explained in detail there, or b) lucidly explained here. Thanks again for anyone with an offering though.

Okay, now on to the meat and potatoes. This question relates to Question 3 of chapter 9. This question is based on promblem 2 which states :"Write a program that makes a modified copy of a text file. In the copy every string Fred (case insensitive) should be replaced with Larry. (So, "Manfred Mann" should become "ManLarry Mann"). The input filename should be given on the command line (don't ask the user), and the output file name should be the corresponding filename ending with .out.

Question 3 states: "Modify the previous program to chage every Fred to Wilma and every Wilma to Fred. Now input like fred&wilma should look like Wilma&Fred in the output".

here's my solution:

#!/usr/bin/perl ## Copyright (C) 2008 Tim Dunphy use strict; my $file = $ARGV[0]; if (!$file) { print "Hey! You didn't give me a file, sucka!\n"; } my $out = $file; $out =~ s/\.\w+?$/.out/; open IN, "<$file" or die "File did not open\n"; open OUT, ">$out" or die "File not available for write.\n"; while (<IN>) { $_ =~ s/fred/\n/i; $_ =~ s/wilma/Fred/i; $_ =~ s/\n/Wilma/; print OUT; }
I do not understand why the output behaves the way it does. Here's what a sample run did to my text file. Here's the input file:
fred wilma wilma fred wilmafred fredwilma wilma&fred fred&wilma


and here is the resulting output, which as you can see is clearly not to my expectations:
Wilma FredWilmaFredWilmaWilma FredWilma WilmaFred Fred&Wilma Wilma&Fred Wilma
What really annoys me, is that I had this problem solved already. But a later exercise completely clobbered this answer and now I can't remember how to fix it!!! :D Anyone who can help me answer this question will help save my sanity.

Thanks!

Replies are listed 'Best First'.
Re: search and replace weird output
by kyle (Abbot) on Feb 25, 2008 at 21:15 UTC

    Every line you read (into $_) has a newline ("\n") at the end of it. You're using a newline to represent the "fred" -> "Wilma" replacement while the "wilma" -> "Fred" replacement is happening, so when it comes time to replace the newline with "Wilma", there's always one at the end of the input.

    I suspect that your earlier solution had a chomp at the beginning of the loop to remove the newline, and then the newline was added again around the time of the print. Like this:

    chomp; $_ =~ s/fred/\n/i; $_ =~ s/wilma/Fred/i; $_ =~ s/\n/Wilma/; print; print "\n";
Re: search and replace weird output
by shmem (Chancellor) on Feb 25, 2008 at 21:24 UTC
    The lines you read in from the file have a trailing newline char (\n), don't they? If so, a newline char is a particular bad choice for a placeholder.
    Anyone who can help me answer this question will help save my sanity.

    Help yourself, by introducing copious debug print statements after each substitution. If you are a candidate for going insane over those kinds of problems, solving the problem for you would only delay your fate. Sometimes the only way to get out of peril is going through it... ;-)

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Help yourself, by introducing copious debug print statements after each substitution. If you are a candidate for going insane over those kinds of problems, solving the problem for you would only delay your fate. Sometimes the only way to get out of peril is going through it... ;-)

      Heh...point well taken sir! Actually the "answer" in the back of the book suggests using the \n as the placeholder. So, you're issue is with Randal, not me! ;)
        Ah, no. I don't have an issue, with neither you nor Randal. But Randal cared to chomp or chop, didn't he?

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}