You are probably familiar with the power of regexes and substitution in Perl, but there are many rarely needed, but incredible features you might not know yet.

A simple example of something you are probably familiar with looks like this:

examples/regex/subst.pl

use 5.010;
use strict;
use warnings;

my $str = "abc 24 def";

$str =~ s/(\d)(\d)/$2$1/;

say $str;   # abc 42 def

Here we capture two digits in the original string and swap them.

That's nice, but what if we would like to replace the two digits by their sum?

Try calculation in substitution

Let's try this:

examples/regex/subst_calc.pl

use 5.010;
use strict;
use warnings;

my $str = "abc 24 def";

$str =~ s/(\d)(\d)/$1 + $2/;

say $str; # abc 2 + 4 def

The result is not the sum of the digits, but the digits themselves with a + sign between them. Of course this is not surprising, after all the second part of a substitution behaves like a normal string in double quotes where we have interpolation, but no code execution.

That's where the e modifier of the regexes/substitutions comes into play.

e as in eval

examples/regex/subst_calc_e.pl

use 5.010;
use strict;
use warnings;

my $str = "abc 24 def";

$str =~ s/(\d)(\d)/$1 + $2/e;

say $str;  # abc 6 def

Here there result is abc 6 def.

Instead of using the substitution string as a plain string, in this case perl called string eval on the string and the result of that eval call was used as the replacement string.

As you can read in that other article string eval can be dangerous as it can execute arbitrary perl code, but if we make sure the input can only be a very restricted set of values then it is secure as well.

Here is a rather dangerous version:

examples/regex/subst_unlink_e.pl

use 5.010;
use strict;
use warnings;

my $str = "file: abc.txt";

$str =~ s/file: (.*)/unlink $1/e;

say $str;  # 1  (or 0 if the file did not exist)

This one will extract the name of a file from the given string and then call unlink on it that will remove the file. The result in the $str variable will be the return value of the unlink function which is 1 on success and 0 on failure.

ee as in eval the eval

If the /e modifier was not crazy enough, Perl allows us to double it to have the /ee modifier. It calls eval on the string on the substitution part and then calls eval again on the results.

I tried to put together an examples here: Given some text that we somehow places in the $text variable, (maybe we read it in from a file), we would like to replace each occurrence off STRING_DIGITS by the result of the function with the same name.

So the string "xy_1" would be replaced by 11 as that's the number returned by the function.

In this solution we have a substitution that matches the strings that look like the functions we are looking for, creates the functions in the first eval, and calls the functions in the second eval provided by /ee. We added g at the end to do this globally.

Here are the 3 version of the substitution with /ee

examples/regex/subst_func_ee.pl

use strict;
use warnings;
use 5.010;

sub xy_1 {
    return 11;
}
sub ab_2 {
    return 22;
}

my $text = 'some xy_1 ab_2';

$text =~ s{(\w+_\d+)}{ "$1()"}eeg;
say $text;    #  some 11 22

with /e:

examples/regex/subst_func_e.pl

use strict;
use warnings;
use 5.010;

sub xy_1 {
    return 11;
}
sub ab_2 {
    return 22;
}

my $text = 'some xy_1 ab_2';

$text =~ s{(\w+_\d+)}{ "$1()"}eg;
say $text;   # some xy_1() ab_2()

without any eval:

examples/regex/subst_func.pl

use strict;
use warnings;
use 5.010;

sub xy_1 {
    return 11;
}
sub ab_2 {
    return 22;
}

my $text = 'some xy_1 ab_2';

$text =~ s{(\w+_\d+)}{ "$1()"}g;
say $text;   # some  "xy_1()"  "ab_2()"

Another example for /ee

examples/regex/subst_str.pl

use 5.010;
use strict;
use warnings;

my $yyxx = 42;

sub f {
   my $c = shift;
   return $c . $c;
}

my $str = "xy";
$str =~ s/(\w)(\w)/ '$' .  f($2) . f($1) /;
say $str;  #  ' .  f(y) . f(x)

examples/regex/subst_str_e.pl

use 5.010;
use strict;
use warnings;

my $yyxx = 42;

sub f {
   my $c = shift;
   return $c . $c;
}

my $str = "xy";
$str =~ s/(\w)(\w)/ '$' .  f($2) . f($1) /e;
say $str;   # $yyxx

examples/regex/subst_str_ee.pl

use 5.010;
use strict;
use warnings;

my $yyxx = 42;

sub f {
   my $c = shift;
   return $c . $c;
}

my $str = "xy";
$str =~ s/(\w)(\w)/ '$' .  f($2) . f($1) /ee;
say $str;  # 42

Examples on CPAN

You might find better or crazier examples for /ee via the grep.cpan.me site.

Another sample article

In the article increasing numbers in a text file you can see another use-cases of /ee.