Perl has some special handling for the readline
function (and the equivalent <>
I/O operator) where it treats the expressions
while (<HANDLE>)
while (readline(HANDLE))
as equivalent to
while (defined($_ = <HANDLE>))
cf.
$ perl -MO=Deparse -e 'f($_) while <>'
f($_) while defined($_ = <ARGV>); <--- implicitly sets $_
-e syntax OK
But this automatic assignment doesn't seem to happen if you hijack the readline
function:
$ 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
Of course, this will make the custom readline
function work incorrectly for a lot of legacy code. The output of this code is "foo"
with the BEGIN block and "bar"
without it, but I want it to be "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
", "bar
");
open X, '<', $bar;
while (<X>) {
print $_; # want and expect to see "BAR
"
}
What options do I have to hijack the readline
function but still get the proper treatment of the while (<...>)
idiom? It's not practical to explicitly convert everything to while (defined($_=<...>))
in all the legacy code.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…