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

Dear Monks, I would like to find a pattern in a doc and replace it with a value from a hash I created. The problem is that the variable I use in the s/// always has no value, but I can succesfully print it on the next line. This is in a while loop. ie..
m/(\d+\.\d+\.\d+\.\d+)/; my $PRTABL=$1; s/\w{3} \w{3} \d+ \d+:\d+:\d+ \d{4}/$clocks{$PRTABL}/; #replaces with +nada? print $clocks{"$PRTABL"}; # This works?

Replies are listed 'Best First'.
Re: replace with hash value?!
by BrowserUk (Patriarch) on Jan 18, 2005 at 22:37 UTC

    Your regexes are inconsistant.

    m/(\d+\.\d+\.\d+\.\d+)/ ## four elements with dots s/\w{3} \w{3} \d+ \d+:\d+:\d+ \d{4}/$clocks{$PRTABL}/ ## three with co +lons

    In the first you are looking for something that could look like "12.34.56.78".

    In the second you are looking for something that looks like "12:23:56".

    If the first one matches, (which it appears to be if the print statements works, then the s/// will never match, and so substitution will never occur.

    Update: This is unnecessary (Thanks chromatic) You will also need to add /e to the substitution for it to interpolate the hash element.

    Finally, there is no reason to do this in two steps, a single substitution would work fine:

    my %clocks = ( '12:34:56.78' => 'Grub up!' ); $_ = 'Stuff here: Mon Feb 12 12:34:56.78 2005 More stuff here'; s/\w{3} \w{3} \d+ (\d+:\d+:\d+\.\d+) \d{4}/$clocks{$1}/; print; ## Will print "Stuff here: Grub up! More stuff here"

    You'll have to make sure that your regex and hash keys match whatever form the (time?) field in your data looks like.

    A final thought. If the field your keying your hash on is a time--with 10ths and hundreths of seconds?--then your hash will need to be enormous:

    60*60*24*100 = 8.64 million keys, which will take approximately 1.2 GB of ram!


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      The reg are not looking for the same thing. the first is looking for an IP address. the ip is the key for the hash, so I save it in $PRTABL=$1. then use it to replace the "time" in the next reg with the value in $clocks{$PRTABL}. except $clocks{$PRTABL} never has a value in s///, however I can print the value on the next line?

        The I would have to guess that your second regex is not matching.

        However, if you want to receive some help--rather than my half arsed guessing--you should try giving us some real information.

        Ie. Some real, runnable code--pasted from your own test program--that demonstrates the failure, including the sample data that causes it to fail.


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.
Re: replace with hash value?!
by trammell (Priest) on Jan 18, 2005 at 22:25 UTC
    You want something more like:
    if (m/(\d+\.\d+\.\d+\.\d+)/) { my $PRTABL=$1; s/\w{3} \w{3} \d+ \d+:\d+:\d+ \d{4}/$clocks{$PRTABL}/; } else { warn "match failed"; }
    Otherwise you're not guaranteed to have a sensible value in $1. You might still have the result from a previous match...
      interesting, but I don't understand why the print statement that follows gives the correct value from the hash?? It seems as if the hash and variable in the s/// works differently from the print statment?
Re: replace with hash value?!
by borisz (Canon) on Jan 18, 2005 at 22:13 UTC
    I guess your pattern \w{3} \w{3} \d+ \d+:\d+:\d+ \d{4} did not match. Thats all.
    Boris
      Boris, It did match that's why I could print it on the next line. thanks
        No, only the m// match, the s/// fail.
        Boris
Re: replace with hash value?!
by kutsu (Priest) on Jan 18, 2005 at 22:18 UTC

    It looks to me like your pattern is not matching, maybe some sample data on what this pattern should be will help us answer your question.

    "Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce