Perl Regex 'e' (eval) modifier with s///

醉酒当歌 提交于 2019-11-26 15:56:28

问题


I'm having a little trouble comprehending this simple use of the /e regex modifier.

my $var = 'testing';
$_ = 'In this string we are $var the "e" modifier.';

s/(\$\w+)/$1/ee;

print;

Returns: "In this string we are testing the "e" modifier."

I cannot see why two 'e' modifiers are required. As far as I can see, $1 should capture '$var' from the string and a single 'e' modifier should then be able to replace the variable with its value. I must be misunderstanding something however, since trying the above code with just one 'e' modifier does not visibly replace anything in the string.

Excuse me for asking such a simple question!

Thanks.


回答1:


It’s not exactly a “simple” question, so don’t beat yourself up.

The issue is that with a single /e, the RHS is understood to be code whose eval’d result is used for the replacement.

What is that RHS? It’s $1. If you evaluated $1, you find that contains the string $var. It does not contain the contents of said variable, just $ followed by a v followed by an a followed by an r.

Therefore you must evaluate it twice, once to turn $1 into $var, then again to turn the previous result of $var into the string "testing". You do that by having the double ee modifier on the s operator.

You can check this pretty easily by running it with one /e versus with two of them. Here’s a demo a both, plus a third way that uses symbolic dereferencing — which, because it references the package symbol table, works on package variables only.

use v5.10;

our $str = q(In this string we are $var the "e" modifier.);
our $var = q(testing);

V1: {
    local $_ = $str; 
    s/(\$\w+)/$1/e;
    say "version 1: ", $_;

}

V2: {
    local $_ = $str;
    s/(\$\w+)/$1/ee;
    say "version 2: ", $_;
}

V3: {
    no strict "refs";
    local $_ = $str;
    s/\$(\w+)/$$1/e;
    say "version 3: ", $_;
}

When run, that produces:

version 1: In this string we are $var the "e" modifier.
version 2: In this string we are testing the "e" modifier.
version 3: In this string we are testing the "e" modifier.



回答2:


To be clear, the s//ee form is not modifying your regex pattern or regex interpretation at all. It is an optional treatment of the replacement side string after the regex is performed. (See PERLOP Regex Quote-like operators)

The e or ee just get mixed into the PATTERN side regex options in the s/PATTERN/REPLACEMENT/msixpodualgcer form.

From Perlop:

Options are as with m// with the addition of the following replacement specific options:

e Evaluate the right side as an expression.
ee  Evaluate the right side as a string then eval the result.
r   Return substitution and leave the original string untouched.

You can see the same e vs ee type behavior in non regex situations, as this example shows:

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

my $var = "var's contents";
my $str='"-> $var <-"';
print eval('$str'), "\n";        # equivalent to s//e
print eval(eval('$str')), "\n";  # equivalent to s//ee

Output:

"-> $var <-"
-> var's contents <-



回答3:


Try the rename utility from the latest perl package with:

rename -v 's/\b(\w)/uc($1)/eg' *

Here, pattern \b find the word boundary, and the e modifier enables evaluation in the substitution, and g replace the all occurrence.

You may also rename to camelCase with:

rename -v 's/\b(\w)/uc($1)/eg' *
rename -v 's/^(\w)/lc($1)/e' *
rename -v 's/\s+//g' *


来源:https://stackoverflow.com/questions/6082219/perl-regex-e-eval-modifier-with-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!