Search code examples
regexperlmoose

Is there a way to use an object's attribute directly in a Perl regex replacement?


I've got a Perl Moose object that contains an attribute I'd like to use as a replacement string in a regex. The idea is to use something like:

$full_string =~ s{FIND_THIS}{$self->replace_string};

Where $self->replace_string is the Moose object's attribute to use. When run as above, it doesn't work as expected. The regex engine thinks '$self' is the variable and the '->' arrow is just a string. Instead of the value of the of the attribute, the output of the replacement ends up looking something like:

ObjectName=HASH(0x7ff458f70778)->replace_string

I know that a simple way to overcome this is to drop the string into a new variable. For example:

my $new_replace_string = $self->replace_string;
$full_string =~ s{FIND_THIS}{$new_replace_string};

My question is if there is a way to avoid creating a new variable and just use the object's attribute directly. (And, ideally without having to add a line of code.) Is this possible?


Solution

  • The most straightforward way is to tell Perl the replacement expression is Perl code to evaluate. The replacement value will be the value returned by that code.

    $full_string =~ s{FIND_THIS}{$self->replace_string}e;
    

    But there exists a trick to interpolate the result of an expression into a string literal (which is what the replacement expression is).

    $full_string =~ s{FIND_THIS}{${\( $self->replace_string )}/;
    

    or

    $full_string =~ s{FIND_THIS}{@{[ $self->replace_string ]}/;
    

    The idea is create a reference and interpolate it using a dereference. In the first, the expression is evaluated in scalar context. In the latter, in list context.