using $1 in a substitution replacement with variable interpolation

Discussion in 'Perl Misc' started by imaginarywave@gmail.com, May 1, 2013.

  1. Guest

    I am trying to use variable interpolation in a replacement string including $1, $2,...
    However, I can't get it to expand $1 into the replacement. I eventually will have the
    $pattern and $replacement variables be read from a configuration file, but even
    setting them manually doesn't work.

    In the example script, you can see that the $1 (which should be 'DEF') is not
    expanded in $new_name, but it is in $new_name2.

    Adding an 'e' flag to the substitution doesn't help.

    How do I fix this?

    Matt

    EXAMPLE CODE:

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

    my $old_name = 'ABC_DEF_GHI';

    my $pattern = 'ABC_(...)_GHI';
    my $replacement = 'CBA_${1}_IHG';

    # using variables - doesn't work
    my $new_name = $old_name;
    $new_name =~ s|$pattern|$replacement|;

    printf("%s --> %s\n", $old_name, $new_name);


    # not using variables - does work
    my $new_name2 = $old_name;
    $new_name2 =~ s|ABC_(...)_GHI|CBA_${1}_IHG|;

    printf("%s --> %s\n", $old_name, $new_name2);


    OUTPUT:

    ABC_DEF_GHI --> CBA_${1}_IHG
    ABC_DEF_GHI --> CBA_DEF_IHG
     
    , May 1, 2013
    #1
    1. Advertising

  2. writes:

    > my $pattern = 'ABC_(...)_GHI';
    > my $replacement = 'CBA_${1}_IHG';
    >
    > # using variables - doesn't work
    > my $new_name = $old_name;
    > $new_name =~ s|$pattern|$replacement|;


    It works to use s/$pattern/qq("$replacement")/ee.

    First we do regular interpolation. With /e the replacement is trated as
    perl code and therefore not interpolated:

    -> s/ABC_(...)_GHI/qq("$replacement")/ee

    Given the match we execute once:

    -> s/ABC_(...)_GHI/"CBA_${1}_IHG"/e

    And once more:

    -> s/ABC_(...)_GHI/CBA_DEF_IHG/

    Reaching the wanted result.

    //Makholm
     
    Peter Makholm, May 1, 2013
    #2
    1. Advertising

  3. On 5/1/2013 12:12 PM, wrote:
    > I am trying to use variable interpolation in a replacement string including $1, $2,...
    > However, I can't get it to expand $1 into the replacement. I eventually will have the
    > $pattern and $replacement variables be read from a configuration file, but even
    > setting them manually doesn't work.
    >
    > In the example script, you can see that the $1 (which should be 'DEF') is not
    > expanded in $new_name, but it is in $new_name2.
    >
    > Adding an 'e' flag to the substitution doesn't help.
    >
    > ...
    >
    > #!/usr/local/bin/perl
    > use strict;
    >
    > my $old_name = 'ABC_DEF_GHI';
    >
    > my $pattern = 'ABC_(...)_GHI';
    > my $replacement = 'CBA_${1}_IHG';
    >
    > # using variables - doesn't work
    > my $new_name = $old_name;
    > $new_name =~ s|$pattern|$replacement|;
    >
    > printf("%s --> %s\n", $old_name, $new_name);
    >


    Perhaps, depending on input string complexity, you could just do this
    and avoid a string eval:

    (my $new_name=$old_name) = "${^PREMATCH}CBA_${1}_IHG${^POSTMATCH}"
    if $old_name =~ m/ABC_(...)_GHI/p;



    --
    Charles DeRykus
     
    Charles DeRykus, May 2, 2013
    #3
  4. On 5/1/2013 4:30 PM, Charles DeRykus wrote:
    >> ...
    >>

    >
    > Perhaps, depending on input string complexity, you could just do this
    > and avoid a string eval:
    >
    > (my $new_name=$old_name) = "${^PREMATCH}CBA_${1}_IHG${^POSTMATCH}"
    > if $old_name =~ m/ABC_(...)_GHI/p;
    >


    Or, simply:

    my $new_name = "${^PREMATCH}CBA_${1}_IHG${^POSTMATCH}"
    if $old_name =~ m/ABC_(...)_GHI/p;

    --
    Charles DeRykus
     
    Charles DeRykus, May 2, 2013
    #4
  5. writes:

    [...]

    > #!/usr/local/bin/perl
    > use strict;
    >
    > my $old_name = 'ABC_DEF_GHI';
    >
    > my $pattern = 'ABC_(...)_GHI';
    > my $replacement = 'CBA_${1}_IHG';
    >
    > # using variables - doesn't work
    > my $new_name = $old_name;
    > $new_name =~ s|$pattern|$replacement|;
    >
    > printf("%s --> %s\n", $old_name, $new_name);


    Using s/// in this way is a little weird. What you are really doing is
    to apply a 'pattern' regex to some string in order to extract certain
    parts out of it and then, you interpolate these parts into a template
    string. I would use something like this for that:

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

    sub interpolate
    {
    my ($in, $pat, $out) = @_;
    my @matches;

    @matches = $in =~ /$pat/;
    $out =~ s/\$\{([0-9]+)\}/$matches[$1 - 1]/g;

    return $out;
    }


    my $old_name = 'ABC_DEF_GHI';

    my $pattern = 'ABC_(...)_(...)';
    my $template = '${2}_${1}_IHG';

    my $new_name = interpolate($old_name, $pattern, $template);


    printf("%s --> %s\n", $old_name, $new_name);
     
    Rainer Weikusat, May 2, 2013
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. \Rob\
    Replies:
    8
    Views:
    688
    Daniel Kirsch
    Feb 24, 2006
  2. Scott
    Replies:
    1
    Views:
    891
    Martin Honnen
    Jul 8, 2004
  3. Dietrich
    Replies:
    3
    Views:
    165
    Joe Smith
    Jul 25, 2004
  4. phrankster

    Variable Interpolation with %%variable

    phrankster, Aug 9, 2005, in forum: Perl Misc
    Replies:
    9
    Views:
    154
    James Taylor
    Aug 14, 2005
  5. Replies:
    2
    Views:
    124
Loading...

Share This Page