【发布时间】:2015-12-16 09:44:09
【问题描述】:
所以我知道 perl 有很多不寻常的语法,但是前几天我在工作中遇到了一个让我感到困惑的代码 sn-p。有人可以向我解释一下这是什么意思:
<<'m'=~m>>
print $a unless $b;
return;
m
;
它看起来像 HEREDOC 语法,但不是我见过的任何形式。
【问题讨论】:
-
您可以访问 Perl 秘密运算符和常量列表here。
标签: perl
所以我知道 perl 有很多不寻常的语法,但是前几天我在工作中遇到了一个让我感到困惑的代码 sn-p。有人可以向我解释一下这是什么意思:
<<'m'=~m>>
print $a unless $b;
return;
m
;
它看起来像 HEREDOC 语法,但不是我见过的任何形式。
【问题讨论】:
标签: perl
这个secret语法被称为ornate double-bladed sword,通常表示为:
<<m=~m>>
Comments here
m
;
这是一个多行 cmets 的 hack,使用 heredoc 语法和匹配运算符 (=~),> 作为分隔符。
注意,由于斜线 / 没有用作匹配的分隔符,因此需要使用“m”运算符。例如$my_var =~ /test/ 等价于$my_var =~ m>test>,而$my_var =~ >test> 则无效。
请注意,sn-p 中的第一个 m 字符用单引号括起来,这意味着不会插入 $a 和 $b 变量。如果省略了这些引号(根据我提供的代码示例),perl 会自动将双引号添加到结束标记,并且将插入任何后续变量。如果不再定义 $a 和 $b 并且您正在使用 use warnings;,这将导致问题。
为了使上面华丽的双刀片示例更容易理解(但仍然不推荐),我们可以这样写:
<<"END" =~ //
Comments here
END
;
注意=~ //是多余的,所以这相当于:
<<"END";
Comments here
END
这只是 void 上下文中的标准 heredoc 语法。
我不建议在生产代码中使用它,因为在 void 上下文中使用字符串会导致问题。此外,即使是最有经验的 perl 程序员,这段代码也会让人头疼,而且阅读和维护起来毫无意义!如果您想创建适当的多线 cmets,那么我建议您按照此处的说明坚持使用 pod How do I enter a multi-line comment in Perl?
希望这能解决问题。
【讨论】:
运行 B::Deparse 有助于理解 perl 如何处理那段代码(假设它位于“test.pl”文件中):
perl -MO=Deparse test.pl
给我们看:
"print \$a unless \$b;\nreturn;\n" =~ //;
test.pl syntax OK
所以,如您所见,perl 正在尝试将一个空的正则表达式匹配到这个字符串:"print \$a unless \$b;\nreturn;\n"
【讨论】: