Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

regex - Perl: Why doesn't eval '/(...)/' set $1?

If a regular expression match occurs inside an eval, changes to the capture-related variables ($1, etc.) are not visible in the outside environment. Is this a bug?

perlop and perlre don't seem to mention any such restriction.

For example:

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

gives:

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

A more succinct demo is:

perl -we '$_="foo"; eval q(/(.*)/;) ; print "GOT:$1
";'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Documentation proof that localized variables are the issue here is in perlvar of 5.14.0:

These variables are read-only and dynamically-scoped, unless we note otherwise.

The dynamic nature of the regular expression variables means that their value is limited to the block that they are in [...]

Note that this bit of documentation is absent from the 5.12.4 perldoc.


The problem is localized variables. My copy of perldoc -f eval (5.12.4) has this to say:

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: [...]

The manpage doesn't make an explicit statement for all such special global variables (like $1, $&, and probably others), but block localization and subsequent restoration is what appears to happen here.

The variables are assigned to inside the eval and the original values are restored once the eval block is left.

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...