Perl имеет специальную обработку для функции readline
(и эквивалентного оператора <>
I / O), где он обрабатывает выражения
while (<HANDLE>)
while (readline(HANDLE))
как эквивалент
while (defined($_ = <HANDLE>))
ср
$ perl -MO=Deparse -e 'f($_) while <>'
f($_) while defined($_ = <ARGV>); <--- implicitly sets $_
-e syntax OK
Но этого автоматического назначения, похоже, не произойдет, если вы перехватите функцию readline
:
$ perl -MO=Deparse -e 'BEGIN {
> *CORE::GLOBAL::readline = sub { }
> }
> f($_) while <>'
sub BEGIN {
*CORE::GLOBAL::readline = sub {
};
}
f($_) while readline(ARGV); <--- doesn't set $_ !
-e syntax OK
Конечно, это приведет к некорректной работе пользовательской функции readline
для большого количества устаревшего кода. Вывод этого кода "foo"
с блоком BEGIN и "bar"
без него, но я хочу, чтобы он был "BAR"
.
use warnings;
BEGIN { *CORE::GLOBAL::readline = \&uc_readline; }
sub uc_readline {
my $line = CORE::readline(shift || *ARGV);
return uc $line if defined $line;
return;
}
($_, $bar) = ("foo\n", "bar\n");
open X, '<', \$bar;
while (<X>) {
print $_; # want and expect to see "BAR\n"
}
Какие варианты у меня есть, чтобы захватить функцию readline
, но все равно получить правильное лечение идиомы while (<...>)
? Непрактично явно конвертировать все в while (defined($_=<...>))
во всем унаследованном коде.