12

以下打印ac | a | bbb | c

    #!/usr/bin/env perl
    use strict;
    use warnings;
    # use re 'debug';
    
    my $str = 'aacbbbcac';
    
    if ($str =~ m/((a+)?(b+)?(c))*/) {
       print "$1 | $2 | $3 | $4\n";
    }

似乎失败的匹配不会重置捕获的组变量。我错过了什么?

4

3 回答 3

21

似乎失败的匹配不会重置捕获的组变量

那里没有失败的比赛。您的正则表达式匹配字符串很好。尽管在某些重复中存在一些内部组的失败匹配。每个匹配的组可能会被为该特定组找到的下一个匹配项所覆盖,或者如果该组在当前重复中不匹配,则保留其与上一个匹配项的值。

让我们看看正则表达式匹配是如何进行的:

  • 第一(a+)?(b+)?(c)场比赛aac。由于(b+)?是可选的,因此不会匹配。在这个阶段,每个捕获组包含以下部分:

    • $1包含整个匹配 -aac
    • $2包含(a+)?部分 -aa
    • $3包含(b+)?部分 - null
    • $4包含(c)部分 -c
  • 因为还有一些字符串要匹配 - bbbcac。继续进行 -(a+)?(b+)?(c)匹配 - bbbc。自从(a+)?是可选的,因此不会匹配。

    • $1包含整个匹配 -bbbc . 覆盖之前的值$1
    • $2不匹配。因此,它将包含先前匹配的文本 -aa
    • $3这次比赛。它包含 -bbb
    • $4火柴c
  • 再次,(a+)?(b+)?(c)将继续匹配最后一部分 -ac

    • $1包含整个匹配 -ac .
    • $2a这次匹配。覆盖之前的值$2。它现在包含 -a
    • $3这次不匹配,因为没有(b+)?部分。和上一场比赛一样——bbb
    • $4匹配c。覆盖上一次匹配的值。它现在包含 - c

现在,字符串中没有任何内容可以匹配。所有捕获组的最终值为:

  • $1-ac
  • $2-a
  • $3-bbb
  • $4- c
于 2013-10-28T18:27:33.487 回答
2

看起来很奇怪,这是“预期的”行为。这是perlre文档的引述:

注意:Perl 中失败的匹配不会重置匹配变量,这样可以更轻松地编写代码来测试一系列更具体的情况并记住最佳匹配。

于 2013-10-28T18:34:46.430 回答
-1

对于括号分组,/(\d+)/文档说使用\1 \2 ...or \g{1} \g{2}。在替换正则表达式部分中使用$1 or $2...会导致错误,例如:scalar found in pattern

# Example to turn a css href to local css.
# Transforms <link href="http://..." into <link href="css/..."

# ... inside a loop ...

my $localcss = $_; # one line from the file
$localcss =~ s/href.+\/([^\/]+\.css")/href="css\/\1/g ;
于 2017-01-20T15:43:55.690 回答