为什么 $_ =~ "regular expression" 在 Perl 中有效?



我知道在Perl中,最常见的有效正则表达式是这样的:

$_ =~ m/regular expression/;
# and "m" can be omit
$_ =~ /regular expression/;

我可以使用qr来创建这样的正则表达式引用:

my $regex = qr/regular expression/;
$_ =~ m/$regex/;
# and "m//" can be omit:
$_ =~ $regex;

但是我已经尝试过这个:

my $str = "regular expression";
$_ =~ $str; # why this is valid?

它没有给我任何错误信息并且工作正常。我不知道为什么,我想应该是这样的:

my $str = "regular expression";
$_ =~ m/$str/;
# or
my $str = "regular expression";
my $regex = qr/$str/;
$_ =~ $regex;

谁能解释为什么$_ =~ $str在Perl中是有效的?

它在 perlre 的"基础知识"下说

尚未存储在某个变量中的模式必须在两端用分隔符分隔。

(以及分隔符(d/r(中不正确的双T(

因此,变量中的模式不需要分隔符。 运算符=~perlop 中的"绑定运算符"中讨论

将标量表达式绑定到模式匹配。

和(强调(

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

运算符不关心其右侧的分隔符,并且可以在运行时从表达式中形成"正则表达式模式"。

perlop 中的"解析引用结构的血腥细节"部分也有助于解决这个问题,除了它本身具有启发性之外。在识别引用的构造并插入包含的文本后,它来到项目符号"解析正则表达式">

经过上述预处理...生成的字符串将传递到 RE 引擎进行编译。

(我的强调(

这是关于 Perl 如何处理引用的构造和 一旦字符串由引号构造形成,就不需要(额外的(分隔符。 前面在">插值"项目符号中讨论了m/RE/(等(,它显示了一些不能与普通字符串一起使用的模式的东西,但这显然不是强制性的。

不过,我建议不要这样做;如您所料,使用qr。 首先,使用字符串(而不是用qr构建的正则表达式(是有限制的。此外,它更容易出现愚蠢的错误。


请注意,虽然对于许多模式,可以使用qr""(或其运算符形式qq()(来准备模式(或将以这种方式解释的字符串( - 但它们并不相同。它们的引用规则非常相似,但qr准备了一个正则表达式,如正则表达式类似引用运算符

。神奇地不同于包含相同字符的字符串...

首先,回想一下,对于qr,您可以使用修饰符。

Perl 努力成为一种自然语言,因此,这些习惯形式,''"",根据上下文可能具有不同的通用形式。这是直接取自 Programming Perl, 4th Edition(第 71 页(,表 2-7 的表格。报价结构:

+-----------+---------+-----------------------+--------------+
| Customary | Generic | Meaning               | Interpolates |
+-----------+---------+-----------------------+--------------+
| ''        | q//     | Literal string        | No           |
+-----------+---------+-----------------------+--------------+
| ""        | qq//    | Literal string        | Yes          |
+-----------+---------+-----------------------+--------------+
| ``        | qx//    | Command execution     | Yes          |
+-----------+---------+-----------------------+--------------+
| ()        | qw//    | Word list             | No           |
+-----------+---------+-----------------------+--------------+
| //        | m//     | Pattern match         | Yes          |
+-----------+---------+-----------------------+--------------+
| s///      | s///    | Pattern substitution  | Yes          |
+-----------+---------+-----------------------+--------------+
| tr///     | y///    | Character translation | No           |
+-----------+---------+-----------------------+--------------+
| ""        | qr//    | Regular expression    | Yes          |
+-----------+---------+-----------------------+--------------+

示例:

在此示例中,字符串将转换为模式。不过,您在这里必须小心,因为当您从双引号字符串构造模式时,您必须转义斜杠。

你可以在这里清楚地看到:

my $pat = "hello\s+world"; #double-slash to escape the slash
if ("hello       world" =~ $pat) {
print "hello, worldn";
}

输出:

hello, world

这由 perlop 中的=~文档回答:

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


只有几件事可以合法地遵循=~

  • 匹配运算符 (m//(
  • 替换运算符 (s///(
  • 音译运算符 (tr///(

现在,Perl可能会给出语法错误,如您所期望的那样,如果在=~的右侧找到任何其他内容。但它反而做了一些更有用的事情。如果它找到上述运算符以外的其他内容,则表达式的结果将用作隐式匹配运算符的模式。

这方便地允许

$s =~ get_pattern()               # do { my $pat = get_pattern(); $s =~ /$pat/ }

$s =~ ( $sub_pat1 . $sub_pat2 )   # do { my $pat = $sub_pat1 . $sub_pat2; $s =~ /$pat/ }

相关内容

最新更新