由于未知错误,嵌套括号的动态正则表达式失败

问题描述 投票:0回答:1

当我在perl中使用动态正则表达式来嵌套括号匹配时,我遇到了一个奇怪的错误。原始字符串是“{... {{}} ...}”,我想用测试grep the pair brace begain,“test {...}”。实际上这组之前可能有很多对支撑,我真的不知道它们的深度。

以下是我的匹配脚本:nesting_parser.pl

#! /usr/bin/env perl
use Getopt::Long;
use Data::Dumper;
my %args = @ARGV;

if(exists$args{'-help'})   {printhelp();}
unless  ($args{'-file'})   {printhelp();}
unless  ($args{'-regex'})  {printhelp();}

my $OpenParents;
my $counts;
my $NestedGuts = qr {
(?{$OpenParents = 0})
  (?>
    (?:
      [^{}]+
| \{ (?{$OpenParents++;$counts++; print "\nLeft:".$OpenParents." ;"})

| \} (?(?{$OpenParents ne 0; $counts++}) (?{$OpenParents--;print "Right: ".$OpenParents." ;"})) (?(?{$OpenParents eq 0}) (?!))
       )*
       )
}x;


my $string  = `cat $args{'-file'}`;
my $partten =      $args{'-regex'} ;

print "####################################################\n";
print "Grep [$partten\{...\}] from $args{'-file'}\n";
print "####################################################\n";


while ($string =~ /($partten$NestedGuts)/xmgs){
 print $1."}\n";
  print $2."####\n";
}
print "Regex has seen $counts brackts\n";
sub printhelp{
print "Usage:\n";
print "\t./nesting_parser.pl -file [file] -regex '[regex expression]'\n";
print "\t[file]   : file path\n";
print "\t[regex]  : regex string\n";
exit;
}

其实我的正则表达式是:

our $OpenParents;
our $NestedGuts = qr {
(?{$OpenParents = 0})
(?>
(?:
[^{}]+
| \{ (?{$OpenParents++;})
| \} (?(?{$OpenParents ne 0}) (?{$OpenParents--})) (?(?{$OpenParents eq 0} (?!))
)*
)
}x;

我在nesting_parser.pl中添加了大括号计数

我还为debug编写了一个字符串生成器:gen_nesting.pl

#! /usr/bin/env perl
use strict;
my $buffer = "{{{test{";

unless ($ARGV[0]) {print "Please specify the nest pair number!\n"; exit}

for (1..$ARGV[0]){
    $buffer.= "\n\{\{\{\{$_\}\}\}\}";
   #$buffer.= "\n\{\{\{\{\{\{\{\{\{$_\}\}\}\}\}\}\}\}\}";
 }
$buffer .= "\n\}}}}";

open TEXT, ">log_$ARGV[0]";
print TEXT $buffer;
close TEXT;

您可以通过生成测试文件

./gen_nesting.pl 1000

它将创建一个名为log_1000的日志文件,其中包含1000行支撑对

现在我们测试我们的匹配脚本:

./nesting_parser.pl -file log_1000 -regex "test" > debug_1000

debug_1000看起来是一个非常完美的结果,匹配成功!但是,当我生成4000行测试日志文件并再次匹配时,它似乎崩溃了:

./gen_nesting.pl 4000
./nesting_parser.pl -file log_4000 -regex "test" > debug_4000

debug_4000的结尾显示

{{{{3277}
####
Regex has seen 26213 brackts

我不知道正则表达式有什么问题,大多数它适用于成对的括号,直到最近我发现它在我尝试匹配超过600,000行的文本文件时崩溃了。

我真的很困惑这个问题,我真的希望能解决这个问题。

谢谢你们!

regex perl
1个回答
1
投票

首先匹配嵌套括号我通常使用Regexp::Common

接下来,我猜你的问题是Perl的正则表达式引擎在匹配32767组之后中断了。您可以通过打开警告并查找Complex regular subexpression recursion limit (32766) exceeded等消息来验证这一点。

如果是这样,你可以使用/g\G以及pos重写你的代码。这个想法是你匹配循环中的括号,就像这个未经测试的代码:

my $start = pos($string);
my $open_brackets = 0;
my $failed;
while (0 < $open_brackets or $start == pos($string)) {
    if ($string =~ m/\G[^{}]*(\{|\})/g) {
        if ($1 eq '{') {
            $open_brackets++;
        }
        else {
            $open_brackets--;
        }
    }
    else {
        $failed = 1;
        break; # WE FAILED TO MATCH
    }
}
if (not $failed and 0 == $open_brackets) {
    my $matched = substr($string, $start, pos($string));
}
© www.soinside.com 2019 - 2024. All rights reserved.