Perl正则表达式和捕获组

时间:2013-10-28 18:16:24

标签: regex perl

以下打印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";
    }

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

感谢,

3 个答案:

答案 0 :(得分:15)

  

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

那里没有失败的比赛。你的正则表达式匹配字符串罚款。虽然在某些重复中内部组有一些失败的匹配。如果该组在当前重复中不匹配,则每个匹配的组可能会被为该特定组找到的下一个匹配项覆盖,或者保留前一个匹配项的值。

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

  • 首先(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
    • $2这次匹配a。覆盖$2中的上一个值。它现在包含 - a
    • $3与此时间不匹配,因为没有(b+)?部分。它与上一场比赛相同 - bbb
    • $4匹配c。覆盖上一场比赛的值。它现在包含 - c

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

  • $1 - ac
  • $2 - a
  • $3 - bbb
  • $4 - c

答案 1 :(得分:1)

奇怪的是,这似乎是“预期的”行为。以下是perlre文档的引用:

  

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

答案 2 :(得分:0)

对于括号分组,/(\d+)/documentation表示要使用 \1 \2 ... \g{1} \g{2}。在替换正则表达式部分中使用$1 or $2...将导致如下错误:在模式中找到的标量

# 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 ;