13

正規表現の一致が eval 内で発生した場合、キャプチャ関連の変数 ($1 など) への変更は外部環境では表示されません。これはバグですか?

perlopperlreは、そのような制限について言及していないようです。

例えば:

 use strict; use warnings;
 $_ = "hello";
 eval '/(.*)/';
 print "GOT: $1\n";

与えます:

Use of uninitialized value $1 in concatenation (.) or string at -e line 1.
GOT:

より簡潔なデモは次のとおりです。

perl -we '$_="foo"; eval q(/(.*)/;) ; print "GOT:$1\n";'
4

3 に答える 3

10

local化された変数がここで問題であるというドキュメントの証拠perlvarは 5.14.0にあります:

特に明記しない限り、これらの変数は読み取り専用で動的スコープです。

正規表現変数の動的な性質は、それらの値がそれらが含まれているブロックに制限されることを意味します [...]

このドキュメントは5.12.4 perldoc には含まれていないことに注意してください。


問題はlocal変数化です。perldoc -f eval(5.12.4)の私のコピーには、次のように書かれています。

The assignment to $@ occurs before restoration of localised
variables, which means a temporary is required if you want to
mask some but not all errors: [...]

$1マンページは、そのようなすべての特別なグローバル変数 ( 、 、およびおそらく他のものなど)について明示的なステートメントを作成していませんが$&、ブロックのローカリゼーションとその後の復元がここで行われているようです。

変数は の内部に割り当てられ、ブロックを離れるevalと元の値が復元されます。eval

use strict; use warnings;
use Test::More;
use constant V => 'hello';

$_ = V;

note '*** block eval';
eval {
        is $_, V, 'input ok';
        /(.*)/;
        is $&, V, 'in eval'; is $1, V, 'in eval';
};
is $&, V, 'after eval'; is $1, V, 'after eval';

note '*** without eval';
is $_, V, 'input ok';
/(.*)/;
is $&, V; is $1, V;

done_testing;
于 2012-06-06T06:54:22.907 に答える
3

実際の質問はすでに回答されているので、ここでタスクをどのように達成するかについての回答を示します。

evalの戻り値を使用するだけで、evalはmatch演算子の戻り値を使用します。$1吸う、避けてください。

use strict; use warnings;
$_ = "hello";
my @r = eval '/(.*)/';
# (
#     "hello"
# )
于 2012-06-06T09:05:49.637 に答える
2

eval内で宣言された字句変数は、evalの終了後に失われます。

于 2012-06-06T06:34:33.930 に答える