【问题标题】:What does the // regex in Perl exactly do?Perl 中的 // 正则表达式究竟做了什么?
【发布时间】:2021-03-19 01:55:29
【问题描述】:

在我正在审核的一个 Perl 项目中,我遇到了很多这样的代码模式:

my ($first, $second) = split(//, $words, 2);
if ($first =~ //i) {
      # do something
}

我不确定这里发生了什么。从执行程序时我可以看出,它在空格上分割$words,但不知道为什么。还有什么是if 条件检查?

我看到了The empty pattern //,但不确定它在这里如何应用,因为在包含上述 sn-p 的函数中没有其他正则表达式。

【问题讨论】:

  • 这就是你所拥有的吗?

标签: regex perl


【解决方案1】:

据我所知,执行程序时它会将 $words 拆分为空格

这是不正确的。

split 将匹配运算符视为 qr// 运算符,允许提供预编译模式,甚至在 qr// 出现之前。

虽然空模式通常对匹配和替换运算符具有特殊含义,但对于用作qr// 运算符split 的匹配运算符而言,情况并非如此。空模式具有始终匹配的通常含义。[1]

因此,split // 导致 split 将字符串拆分为单个字符。

$ perl -M5.010 -e'say join ":", split(//, "abcd")'
a:b:c:d

在您的情况下,第三个参数将 split 限制为一次剪切。

$ perl -M5.010 -e'say join ":", split(//, "abcd", 2)'
a:bcd

所以$first 接收$words 中字符串的第一个字符,$second 接收字符串的其余部分。


所以剩下$first =~ //i

匹配运算符的空模式会导致使用最后一个成功匹配的正则表达式。

$ perl -M5.010 -e'$_ = "foo"; /(.)oo/; /(.)ar/; "moo" =~ //; say $1;'
m

一开始它是一个不起眼的功能,在这里它是在split 之后使用的。这是可怕的代码。 split 执行的匹配算吗?测试表明答案是否定的。

所以我们无法从您发布的代码中判断 $first =~ //i 做了什么,因为它使用了之前未显示的匹配模式。


  1. 这应该很清楚为什么:

    "aaaaa" =~ /(?:aaa)/   # Matches 3 chars at pos 0.
    "aaaaa" =~ /(?:aa)/    # Matches 2 chars at pos 0.
    "aaaaa" =~ /(?:a)/     # Matches 1 chars at pos 0.
    "aaaaa" =~ /(?:)/      # Matches 0 chars at pos 0.
    

【讨论】:

    【解决方案2】:

    来自split 文档:

    However, this:
    
        print join(':', split(//, 'abc')), "\n";
    
    uses empty string matches as separators to produce the output
    "a:b:c"; thus, the empty string may be used to split EXPR into a
    list of its component characters.
    
    As a special case for "split", the empty pattern given in match
    operator syntax ("//") specifically matches the empty string,
    which is contrary to its usual interpretation as the last
    successful match.
    

    然后,来自perlop(你已经看到了):

    The empty pattern //
    
    If the PATTERN evaluates to the empty string, the last successfully
    matched regular expression is used instead. In this case, only the g
    and c flags on the empty pattern are honored; the other flags are
    taken from the original pattern. If no match has previously succeeded,
    this will (silently) act instead as a genuine empty pattern (which
    will always match).
    

    前面的正则表达式不需要在同一个函数中。无论之前的正则表达式 及时 是之前的正则表达式。这就是人们不应该依赖这种东西的原因之一,除非他们还控制事件的顺序,例如在成功应用模式后立即使用它。

    【讨论】:

      猜你喜欢
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 2012-07-23
      • 2016-09-10
      • 2023-03-15
      • 2012-10-17
      相关资源
      最近更新 更多