Perl: Почему eval '/ (…) /' не устанавливает $ 1?

Если в eval происходит совпадение с регулярным выражением, изменения переменных, связанных с захватом ($ 1 и т. Д.), Не видны во внешней среде. Это ошибка?

Perlop а также Perlre Похоже, не упомянул о таком ограничении.

Например

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

gives:

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

Более краткая демонстрация:

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

Ответы на вопрос(3)

поэтому вот ответ, как вы решаете задачу.

Просто используйте возвращаемые значения eval, который в свою очередь использует возвращаемые значения оператора соответствия.$1 Отстой, избегай.

use strict; use warnings;
$_ = "hello";
my @r = eval '/(.*)/';
# (
#     "hello"
# )

объявленные в eval, будут потеряны после его окончания.

 Lumi06 июн. 2012 г., 08:46
Раньше я думал о$1 (а также$&, в этом отношении) какГлобальны переменные, а не Лексического те.
 Matteo06 июн. 2012 г., 08:52
@ Lumi они глобальные, но неявно объявляются только при первом использовании (см. Пример в моем ответе)
 Lumi06 июн. 2012 г., 09:25
@ Маттео - Нет, понятие Объявить глобальные переменные (действительно Пакет переменные) в Perl вводит в заблуждение. Нет необходимости объявлять их, ни встроенные, ни какие-либо пользователь может добавить. Это просто значения, хранящиеся в пространстве имен. нужно для декларации или полной квалификации возникает только сstrict прагма:my -декларация,our -объявление (прилагается к пакету, но имеет лексическую область видимости) или полная квалификация не встроенных глобальных переменных.
 Matteo06 июн. 2012 г., 09:28
@ Lumi Да, я также нашел соответствующую документацию (которую вы также добавили в свой ответ). Поведение теперь имеет смысл: -)

localized переменные являются проблемой здесь вperlvar из 5.14.0:

Эти переменные доступны только для чтения и имеют динамическую область видимости, если не указано иное.

Динамическая природа переменных регулярного выражения означает, что их значение ограничено блоком, в котором они находятся [...]

Обратите внимание, что эта часть документации является отсутствует с 5.12.4 perldoc.

Проблема вlocalized переменные. Моя копияperldoc -f eval (5.12.4) есть что сказать:

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

Manpage не делает явного утверждения для всех таких специальных глобальных переменных (например,$1, $& и, возможно, другие), но здесь, по-видимому, происходит блокировка локализации и последующее восстановление.

Переменные назначены внутриeval и исходные значения восстанавливаются послеeval Блок остался.

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

$_ = V;

note '*** block eval';
eval {
        is $_, V, 'input ok';
        /(.*)/;
        is 
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;
amp;, V, 'in eval'; is $1, V, 'in eval'; }; is
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;
amp;, V, 'after eval'; is $1, V, 'after eval'; note '*** without eval'; is $_, V, 'input ok'; /(.*)/; is
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;
amp;, V; is $1, V; done_testing;
 Lumi06 июн. 2012 г., 09:28
@ Matteo - Как уже говорилось в другом комментарии на этой странице,$1 не "неявно объявлено". См. Обновление в верхней части моего ответа для получения справочной документации, объясняющей эту проблему.

Ваш ответ на вопрос