为什么`$ str1 =〜" foo"`被识别为`$ str1 = ~m / foo /`(而不是语法错误)?

时间:2016-09-14 19:27:19

标签: regex perl

我最近看到了一些不熟悉Perl的人的代码。 他想比较两个字符串的平等但不知道 eq运算符,所以他使用=~这样:

my $str1 = 'foobar';
my $str2 = 'bar';
if ( $str1 =~ $str2 ) {
    print "strings are equal\n";
}

另一个片段是

if ( $str1 =~ "foo" ) {
    print "string equals 'foo'\n";
}

当然,只需阅读$str1 eq $str2$str1 eq "foo"即可避免误报。

我通过Deparse运行代码,它说一切正常:

$ perl -MO=Deparse -e 'use strict; 
                       use warnings; 
                       my $str1="foobar"; 
                       my $str2="bar"; 
                       $str1 =~ $str2; 
                       $str1 =~ "bar";'
use warnings;
use strict;
my $str1 = 'foobar';
my $str2 = 'bar';
$str1 =~ /$str2/;
$str1 =~ /bar/;
-e syntax OK

我查看了docs,但是根据我的理解 情况如下:

  • 一般语法为m/pattern/
  • 使用m和您选择的分隔符而不是/(但要注意'?具有特殊含义)
  • 不要使用m,但分隔符必须/

但显然Perl将$str1 =~ "foo"理解为$str1 =~ m/foo/,但不存在m。这是为什么?我预计会出现语法错误。

2 个答案:

答案 0 :(得分:5)

  

我希望这是一个语法错误。

perlop

中引用=~的文档
  

如果右参数是表达式而不是搜索模式,替换或音译,则在运行时将其解释为搜索模式。

  

但显然Perl将$str1 =~ "foo"理解为$str1 =~ m/foo/,但不存在m。那是为什么?

为什么不呢?如果在其RHS上没有匹配,替换或音译操作符,我想不出有=~暗示匹配运算符的原因。我用

$s =~ /foo/

$s =~ "foo"

但我用过

$s =~ $re

特别是当$re的值是由qr//编译的模式时。

答案 1 :(得分:3)

=~运算符需要左边的标量表达式和右边的模式匹配。来自the documentation

  

Binary" =〜"将标量表达式绑定到模式匹配。某些操作默认搜索或修改字符串$ _。此运算符使该类操作在其他字符串上运行。正确的参数是搜索模式,替换或音译。左参数是应该搜索,替换或音译的内容,而不是默认的$ _   ...
  如果正确的参数是表达式而不是搜索模式,替换或音译,则在运行时将解释为搜索模式。

右手边的实际解释可能是......棘手的。详细信息可以在Perl文档的"Gory Details of Parsing Quoted Constructs"中找到,其摘要是:

  

当出现可能有多种不同解释的内容时,Perl使用 DWIM (即“我的意思和#34;”原则来选择最可能的解释。这种策略非常成功,以至于Perl程序员通常不会怀疑他们所写内容的矛盾心理。但Perl的观念不时与作者的真实含义大不相同   ...
  最重要的Perl解析规则是下面讨论的第一个规则:在处理带引号的构造时,Perl首先找到该构造的结尾,然后解释其内容。如果您了解此规则,则可以在第一次阅读时跳过本节的其余部分。其他规则可能比第一个规则更不频繁地与用户的期望相矛盾。