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

Hi, I havve following code where i am trying to substitute with hash in regex.

my %replace = ('111'=>bar, '222'=>world, '333'=>perl); my $find = join "|", sort keys %replace; my $str = "f111,f222,f333"; $str =~ s/f(0-9)/$replace{$1}/g;

I am expecting the output as "bar, world, perl". but instead the output is "11,22,33". neone suggest me whts wrong pls?

Replies are listed 'Best First'.
Re: problem with substitute in regexp
by moritz (Cardinal) on Nov 10, 2011 at 08:45 UTC

    [0-9] matches exactly one digit, so the first match is f1 and $1 is 1. There's no such hash key, so it interpolates undef, which stringifies to the empty string.

    It would help to write ([0-9]+) or ([0-9]{3}), depending on what your data looks like.

Re: problem with substitute in regexp
by ansh batra (Friar) on Nov 10, 2011 at 09:01 UTC
    my %replace = ('111'=>bar, '222'=>world, '333'=>perl); my $find = join "|", sort keys %replace; my $str = "f111,f222,f333"; $str =~ s/f([0-9]+)/$replace{$1}/g; print "$str\n";
    output
    bar,world,perl


    just as moritz said!!!

      ansh batra:

      While it *will* give the proper output, it's rather ugly, and would give a poor example for other initiates. I'd suggest a little tune-up:

      • If you compile under strict, it will report bare words it the first line.
      • The second line does nothing, so it just makes things harder to read.
      • You're capturing the digits group, but ignoring the group. Remove the parenthesis.

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

      Update: AnomalousMonk pointed out my blindness: he *is* using the capture group. D'oh!

        roboticus
        #! /usr/bin/perl -w use strict; my %replace = ('111'=>"bar", '222'=>"world", '333'=>"perl"); my $str = "f111,f222,f333"; $str =~ s/f([0-9]+)/$replace{$1}/g; print "$str\n";

        • used strict and warnings
        • forgot to remove the second line . it was there in original code
        • dint get your third point
        • and sorry for these mistakes . i dont know how i am into bad/lazy programming habits. thanks for reminding
      Hi,

      Even if  my $find=join "|", sort keys %replace; is removed, the output I am getting is the same. So, just wonder the use of that in this context since this is already sorted.

Re: problem with substitute in regexp
by AnomalousMonk (Archbishop) on Nov 10, 2011 at 16:19 UTC

    Here's an example using the keys of the hash to generate the substitution search regex.

    >perl -wMstrict -le "my %replace = ( '111' => 'bar', '1111' => 'world', '333' => 'perl', ); my $find = join '|', reverse sort keys %replace; ;; my $str = 'f111,f1111,f333'; $str =~ s{ f ($find) }{$replace{$1}}xmsg; print qq{'$str'}; " 'bar,world,perl'

    upaksh: For extra credit (after you've perused Markup in the Monastery and Writeup Formatting Tips for penance), why is the  reverse sort necessary in generating the substitution search regex for the example replacement mapping given? What happens if the  reverse is left out of the sort? (Well, it "doesn't work right", but why?)

Re: problem with substitute in regexp
by upaksh (Novice) on Nov 11, 2011 at 11:28 UTC
    thanks guys... also I found the solution with following. $str =~ s/f(\d+)/$replace{$1}/g;