Perl - 右大括号位于左大括号之前。它是如何工作的?

Che*_*tar 4 perl

我遇到了这个解决方案来反转文件的内容:

$ cat f1
abc
def
ghi
jkl

$ perl -ne 'push @arr,$_;}{print reverse @arr;' f1
jkl
ghi
def
abc
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下大括号是如何工作的吗?我很困惑,右括号在左括号之前。

Gil*_*il' 5

这是因为该-n开关实际上在源代码周围添加了大括号。正如手册所说:

-n 导致 Perl 假设程序周围有以下循环,这使得它迭代文件名参数,有点像sed -nor awk

LINE:
  while (<>) {
      ...             # your program goes here
  }
Run Code Online (Sandbox Code Playgroud)

这不仅仅意味着 Perl 将围绕程序运行等效的循环。它实际上添加了此处显示的前缀和后缀(具有不同的间距)。引用源码(toke.c):

            if (PL_minus_n || PL_minus_p) {
                sv_catpvs(PL_linestr, "LINE: while (<>) {"/*}*/);
Run Code Online (Sandbox Code Playgroud)

        } else if (!PL_in_eval && PL_minus_n) {
            sv_catpvs(linestr, /*{*/";}");
Run Code Online (Sandbox Code Playgroud)

该函数sv_catpvs将指定的字符串附加到包含要解析的源代码的中间缓冲区。我认为之前也插入了换行符;}(因为#-e字符串中没有将它们注释掉)。-e在这两个调用之间的某个位置,还附加了的内容。

其他开关如-p-F-E等的工作原理类似。

因此你的代码示例运行

LINE: while (<>) {push @arr,$_;}{print reverse @arr;;}
Run Code Online (Sandbox Code Playgroud)

在适当的间距下,是。

LINE: while (<>) {
    push @arr,$_;
}
{
    print reverse @arr;
    ;
}
Run Code Online (Sandbox Code Playgroud)

消除未使用的标签、第二组大括号(分组不需要)和空指令(lone ;),即:

while (<>) {
    push @arr,$_;
}
print reverse @arr;
Run Code Online (Sandbox Code Playgroud)

循环按@arr顺序添加行,循环后的指令以相反的顺序打印它们。