regex – 使用Perl正则表达式捕获C样式代码块之前和之后的文本

前端之家收集整理的这篇文章主要介绍了regex – 使用Perl正则表达式捕获C样式代码块之前和之后的文本前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图使用Perl正则表达式捕获C风格代码块之前和之后的一些文本.到目前为止,这就是我所拥有的:
use strict;
use warnings;

my $text = << "END";
int max(int x,int y)
{
    if (x > y)
    {
        return x;
    }
    else
    {
        return y;
    }
}
// more stuff to capture
END

# Regex to match a code block
my $code_block = qr/(?&block)
(?(DEFINE)
    (?<block>
        \{                # Match opening brace
            (?:           # Start non-capturing group
                [^{}]++   #     Match non-brace characters without backtracking
                |         #     or
                (?&block) #     Recursively match the last captured group
            )*            # Match 0 or more times
        \}                # Match closing brace
    )
)/x;

# $2 ends up undefined after the match
if ($text =~ m/(.+?)$code_block(.+)/s){
    print $1;
    print $2;
}

我遇到了第二个捕获组在比赛后没有初始化的问题.在DEFINE块之后没有办法继续正则表达式吗?我认为这应该工作正常.

$2应该包含代码块下方的注释,但它没有,我找不到一个很好的理由为什么这不起作用.

解决方法

捕获组按照它们在正则表达式中出现的顺序从左到右编号,而不是按照它们匹配的顺序编号.以下是正则表达式的简化视图:
m/
  (.+?)  # group 1
  (?:  # the $code_block regex
    (?&block)
    (?(DEFINE)
      (?<block> ... )  # group 2
    )
  )
  (.+)  # group 3
/xs

命名组也可以作为编号组访问.

第二组是块组.但是,该组仅用作命名子模式,而不是捕获.因此,2美元的捕获值是undef.

因此,代码块之后的文本将存储在捕获$3中.

有两种方法可以解决这个问题:

>对于复杂的正则表达式,仅使用命名捕获.一旦从正则表达式对象组装正则表达式,或者如果捕获是有条件的,则考虑将正则表达式复杂化.这里:

if ($text =~ m/(?<before>.+?)$code_block(?<afterwards>.+)/s){
    print $+{before};
    print $+{afterwards};
}

>将所有定义放在最后,它们不会弄乱您的捕获编号.例如,$code_block正则表达式只会定义一个命名模式,然后您可以显式调用该模式.

猜你在找的Perl相关文章