That's because the -n
switch literally adds curly brackets around the source code. As the manual says:
-n
causes Perl to assume the following loop around your program, which makes it iterate over filename arguments somewhat like sed -n
or awk
:
LINE:
while (<>) {
... # your program goes here
}
This doesn't just mean that Perl will run an equivalent loop around the program. It actually adds the prefix and suffix shown here (with different spacing). Citing the source code (toke.c
):
if (PL_minus_n || PL_minus_p) {
sv_catpvs(PL_linestr, "LINE: while (<>) {"/*}*/);
and
} else if (!PL_in_eval && PL_minus_n) {
sv_catpvs(linestr, /*{*/";}");
The function sv_catpvs
appends the specified string to an intermediate buffer containing the source code to parse. I think a line break is also inserted before ;}
(since #
in the -e
string doesn't comment them out). Somewhere between those two calls, the content of -e
is also appended.
Other switches like -p
, -F
, -E
, etc. work similarly.
Thus your code example runs
LINE: while (<>) {push @arr,$_;}{print reverse @arr;;}
which, with proper spacing, is.
LINE: while (<>) {
push @arr,$_;
}
{
print reverse @arr;
;
}
Eliminating the unused label, the second group of braces (which is not necessary for grouping) and the empty instruction (lone ;
), that's:
while (<>) {
push @arr,$_;
}
print reverse @arr;
The loop adds lines to @arr
in order, and the instruction after the loop prints them in reverse order.