web-dev-qa-db-ja.com

Perl Regex 'e'(eval)修飾子とs ///

/ e regex修飾子のこの単純な使用を理解するのに少し問題があります。

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

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

print;

戻り値:「この文字列では、「e」修飾子をテストしています。」

なぜ2つの「e」修飾子が必要なのかわかりません。私が見る限り、$ 1は文字列から '$ var'をキャプチャし、単一の 'e'修飾子は変数をその値に置き換えることができるはずです。ただし、上記のコードを 'e'修飾子1つだけで試しても、文字列内の何も目に見えて置き換えられないので、私は何かを誤解しているに違いありません。

こんな簡単な質問をしてしまってすみません!

ありがとう。

31
pb149

これは必ずしも「単純な」質問ではないので、打ちのめさないでください。

問題は、単一の_/e_では、RHSはevalの結果が置換に使用されるコードであると理解されることです。

そのRHSとは何ですか? _$1_です。 _$1_を評価した場合、これにはstring_$var_が含まれていることがわかります。変数の内容は含まれていません。_$_の後にvが続き、aの後にrが続きます。

したがって、2回評価する必要があります。1回は_$1_を_$var_に変換し、次にもう一度、以前の_$var_の結果を文字列_"testing"_に変換します。これを行うには、 ee演算子 に二重のs修飾子を付けます。

これは、1つの_/e_と2つ実行することで簡単に確認できます。以下は、両方のデモと、シンボリック逆参照を使用する3番目の方法です。これは、パッケージシンボルテーブルを参照するため、パッケージ変数でのみ機能します。

_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: ", $_;
}
_

実行すると、以下が生成されます。

_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.
_
39
tchrist

明確にするために、s//eeフォームは正規表現パターンや正規表現解釈をまったく変更していません。これは、正規表現が実行された後の置換側ストリングのオプションの処理です。 ( PERLOP正規表現の引用のような演算子)を参照

eまたはeeは、s/PATTERN/REPLACEMENT/msixpodualgcerフォームのPATTERN側の正規表現オプションに混合されます。

Perlopから:

オプションは、m //と同じですが、次の置換固有のオプションが追加されています。

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.

次の例に示すように、正規表現以外の状況でも同じeeeタイプの動作を確認できます。

#!/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

出力:

"-> $var <-"
-> var's contents <-
9
the wolf

最新のPerlパッケージのrenameユーティリティを次のように試してください。

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

ここでは、パターン\b単語の境界を見つけ、e修飾子は置換の評価を有効にし、gはすべての出現を置き換えます。

次のようにキャメルケースに名前を変更することもできます:

rename -v 's/\b(\w)/uc($1)/eg' *
rename -v 's/^(\w)/lc($1)/e' *
rename -v 's/\s+//g' *
0
Xiè Jìléi