由于未知错误,嵌套括号的动态正则表达式失败
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由于未知错误,嵌套括号的动态正则表达式失败相关的知识,希望对你有一定的参考价值。
当我在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 "
Left:".$OpenParents." ;"})
| } (?(?{$OpenParents ne 0; $counts++}) (?{$OpenParents--;print "Right: ".$OpenParents." ;"})) (?(?{$OpenParents eq 0}) (?!))
)*
)
}x;
my $string = `cat $args{'-file'}`;
my $partten = $args{'-regex'} ;
print "####################################################
";
print "Grep [$partten{...}] from $args{'-file'}
";
print "####################################################
";
while ($string =~ /($partten$NestedGuts)/xmgs){
print $1."}
";
print $2."####
";
}
print "Regex has seen $counts brackts
";
sub printhelp{
print "Usage:
";
print " ./nesting_parser.pl -file [file] -regex '[regex expression]'
";
print " [file] : file path
";
print " [regex] : regex string
";
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!
"; exit}
for (1..$ARGV[0]){
$buffer.= "
{{{{$_}}}}";
#$buffer.= "
{{{{{{{{{$_}}}}}}}}}";
}
$buffer .= "
}}}}";
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行的文本文件时崩溃了。
我真的很困惑这个问题,我真的希望能解决这个问题。
谢谢你们!
首先匹配嵌套括号我通常使用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));
}
以上是关于由于未知错误,嵌套括号的动态正则表达式失败的主要内容,如果未能解决你的问题,请参考以下文章