为什么$ _ =〜“正则表达式”在Perl中有效?

时间:2018-09-22 04:37:19

标签: 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中有效吗?

3 个答案:

答案 0 :(得分:7)

它在"The basics" in perlre下显示

  

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

(以及错误的tt`)

因此,变量中的模式不需要定界符。 "Binding operators" in perlop

中讨论的运算符=~
  

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

和(我强调)

  

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

运算符不关心其右侧的分隔符,并且可以在运行时在表达式之外形成“ regex模式”。

"Gory details of parsing quoted constructs" in perlop节也对此有所帮助,除了本身具有启发性。确定引用的构造并插入包含的文本后,它出现在项目符号“解析正则表达式”中

  

经过上述预处理后,结果字符串被传递到RE引擎进行编译。

(我的重点)

这是有关Perl如何处理引用的构造和 一旦字符串由引用的构造构成,就不需要(额外的)定界符。 m/RE/(等)已在前面的“ 插值”项目符号中进行了讨论,其中显示了一些不能与普通字符串一起用于模式的内容,但是显然不强制拥有。

我还是建议不要这样做;如您所愿,使用qr。一方面,使用字符串(而不是使用qr构建的正则表达式)是有限制的。而且,它更容易出现愚蠢的错误。


请注意,尽管用于许多模式,但可以使用qr""(或其运算符形式qq())来准备模式(或字符串)这将以这种方式进行解释)-它们并不相同。他们的报价规则非常相似,但是qr会准备一个正则表达式,正则表达式放在Regexp Quote-Like Operators

  

...魔术上不同于包含相同字符的字符串...

请记住,使用qr可以使用修饰符。

答案 1 :(得分:3)

Perl努力成为一种自然语言,因此,这些惯用形式''""根据上下文可能具有不同的通用形式。这是直接从Programming Perl, 4th Edition (pg. 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, world\n";
}

输出:

hello, world

答案 2 :(得分:1)

perlop=~的文档对此进行了回答:

  

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


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

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

现在,如果在=~的右侧找到了其他任何内容,Perl 可以给出语法错误。但这反而会做更多有用的事情。如果发现上述运算符以外的内容,则将表达式的结果用作隐式match运算符的模式。

这很方便

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

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