4

I came across this solution to reverse the content of a file :

$ cat f1
abc
def
ghi
jkl

$ perl -ne 'push @arr,$_;}{print reverse @arr;' f1
jkl
ghi
def
abc

Could someone please explain how the curly brackets work ? I'm confused, the closing bracket comes before the opening one.

4
5

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.