微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正则表达式 – 我可以使用Perl正则表达式来匹配平衡文本吗?

我想在Perl中匹配括号中的文字.我怎样才能做到这一点?

这是official perlfaq一个问题.我们是importing the perlfaq to Stack Overflow.

这是 official FAQ answer减去任何后续的编辑.

您的第一次尝试应该是Text::Balanced模块,它是Perl 5.8中的Perl标准库.它具有处理棘手文字的各种功能. Regexp::Common模块还可以通过提供可以使用的罐头模式来帮助.

从Perl 5.10开始,您可以使用递归模式将平衡文本与正则表达式相匹配.在Perl 5.10之前,你必须诉诸各种各样的技巧,比如在(?? {})序列中使用Perl代码.

以下是使用递归正则表达式的示例.目标是捕获尖括号中的所有文本,包括嵌套尖括号中的文本.此示例文本具有两个“主要”组:一个具有一个嵌套级别的组和一个具有两个嵌套级别的组.尖括号中共有五组:

I have some <brackets in <nested brackets> > and
<another group <nested once <nested twice> > >
and that's it.

匹配平衡文本的正则表达式使用两个新的(到Perl 5.10)正则表达式特征.这些在perlre中涵盖,此示例是该文档中的一个修改版本.

首先,添加新的占有者到任何量词发现最长的匹配,不回溯.这很重要,因为你想通过递归处理任何尖括号,而不是回溯.组[^]找到一个或多个非角括号而不进行回溯.

第二,新(?PARNO)是指由PARNO给出的特定捕获组中的子模式.在以下正则表达式中,第一个捕获组查找(并记住)平衡文本,并且您需要在第一个缓冲区内具有相同的模式以覆盖嵌套文本.这是递归部分. (?1)将外部捕获组中的模式用作正则表达式的独立部分.

把它们放在一起,你有:

#!/usr/local/bin/perl5.10.0

my $string =<<"HERE";
I have some <brackets in <nested brackets> > and
<another group <nested once <nested twice> > >
and that's it.
HERE

my @groups = $string =~ m/
        (                   # start of capture group 1
        <                   # match an opening angle bracket
            (?:
                [^<>]++     # one or more non angle brackets,non backtracking
                  |
                (?1)        # found < or >,so recurse to capture group 1
            )*
        >                   # match a closing angle bracket
        )                   # end of capture group 1
        /xg;

$" = "\n\t";
print "Found:\n\t@groups\n";

输出结果表明Perl发现了两个主要组:

Found:
    <brackets in <nested brackets> >
    <another group <nested once <nested twice> > >

有一点额外的工作,你可以得到所有的组在尖括号,即使它们在其他尖括号.每次获得平衡匹配时,请删除其外部分隔符(这是您刚刚匹配的分隔符,因此不再匹配),并将其添加到要处理的字符串中.继续做,直到你没有比赛:

#!/usr/local/bin/perl5.10.0

my @queue =<<"HERE";
I have some <brackets in <nested brackets> > and
<another group <nested once <nested twice> > >
and that's it.
HERE

my $regex = qr/
        (                   # start of bracket 1
        <                   # match an opening angle bracket
            (?:
                [^<>]++     # one or more non angle brackets,non backtracking
                  |
                (?1)        # recurse to bracket 1
            )*
        >                   # match a closing angle bracket
        )                   # end of bracket 1
        /x;

$" = "\n\t";

while( @queue )
    {
    my $string = shift @queue;

    my @groups = $string =~ m/$regex/g;
    print "Found:\n\t@groups\n\n" if @groups;

    unshift @queue,map { s/^<//; s/>$//; $_ } @groups;
    }

输出显示所有组.最外面的比赛首先显示,并且以后会显示嵌套的比赛:

Found:
    <brackets in <nested brackets> >
    <another group <nested once <nested twice> > >

Found:
    <nested brackets>

Found:
    <nested once <nested twice> >

Found:
    <nested twice>

原文地址:https://www.jb51.cc/regex/357163.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐