为旧的Perl版本重写递归正则表达式
发布时间:2020-12-15 23:34:04 所属栏目:大数据 来源:网络整理
导读:以下代码可以与Perl(v5.16.2)一起使用.但是,当我使用Perl v5.8.9运行它时,它会抱怨以下正则表达式.如何以与Perl v5.8.9一起使用的方式重写此正则表达式. (我无法更新版本). 正则表达式: use strict;use warnings;our %formula_per_k;INIT { # List all func
以下代码可以与Perl(v5.16.2)一起使用.但是,当我使用Perl v5.8.9运行它时,它会抱怨以下正则表达式.如何以与Perl v5.8.9一起使用的方式重写此正则表达式. (我无法更新版本).
正则表达式: use strict; use warnings; our %formula_per_k; INIT { # List all functions that you want to allow in formulas. All other words will be interpretted as variables. my @FORMULA_FUNCS = qw(sqrt exp log); # Load the data via a file. my $data = do {local $/; <DATA>}; # Parse K blocks while ($data =~ m{ ^K s+ (w+) s* { ( (?: [^{}]+ | {(?2)} )* ) # Matched braces only. } }mgx) { my ($name,$params) = ($1,$2); # Parse LOL block next if $params !~ m{ LOL s* { ( (?: [^{}]+ | {(?1)} )*? ) # Matched braces only. } }mx; my $lol = $1; # Start building anonymous subroutine my $conditions = ''; # Parse Conditions and Formulas while ($lol =~ m{ COND s* { (.*?) } s* FORMULA s* { (.*?) } }gx) { my ($cond,$formula) = ($1,$2); # Remove Excess spacing and translate variable into perl scalar. for ($cond,$formula) { s/^s+|s+$//g; s{([a-zA-Z]+)}{ my $var = $1; $var = "$hashref->{$var}" if ! grep {$var eq $_} @FORMULA_FUNCS; $var }eg; } $conditions .= "return $formula if $cond; "; } my $code = "sub {my $hashref = shift; ${conditions} return; }"; my $sub = eval $code; if ($@) { die "Invalid formulas in $name: $@"; } $formula_per_k{$name} = $sub; } } sub formula_per_k { my ($k,$vars) = @_; die "Unrecognized K value '$k'" if ! exists $formula_per_k{$k}; return $formula_per_k{$k}($vars); } print "'K1',{d => .1} = " . formula_per_k('K1',{d => .1}) . "n"; print "'K1',{d => .05} = " . formula_per_k('K1',{d => .05}) . "n"; print "'K3',{d => .02} = " . formula_per_k('K3',{d => .02}) . "n"; print "'K3',{d => .021} = " . formula_per_k('K3',{d => .021}) . "n"; __DATA__ ... #OTHER STUFFS K K1 { LOL { COND { d < 0.01 } FORMULA { -0.2 + 3.3*sqrt(d) } COND { d >= 0.01 } FORMULA { -0.2 + 3.3*sqrt(d+0.4) } } } ... #OTHER STUFFS K K2 { LOL { COND { d < 0.03 } FORMULA { -2.2 + 1.3*sqrt(d) } COND { d >= 0.03 } FORMULA { -2.2 + 1.3*sqrt(d+0.8) } } } ... #OTHER STUFFS K K3 { LOL { COND { d < 0.02 } FORMULA { -4.3 + 0.3*sqrt(d) } COND { d >= 0.02 } FORMULA { -4.3 + 0.3*sqrt(d+0.3) } } } ... #OTHER STUFF 输出: 'K1',{d => .1} = 2.13345237791561 'K1',{d => .05} = 2.01370729772479 'K3',{d => .02} = -4.13029437251523 'K3',{d => .021} = -4.13002941430942 错误: Sequence (?1...) not recognized in regex; marked by <-- HERE in m/ ^K s+ M3 s* { ( (?: [^{}]+ | {(?2 <-- HERE )} )* ) # Matched braces only. } / at ./code.pl line 215,<RFILE> line 12. 更新: 解决方法
在引入(?PARNO)之前,我们必须使用(?? {code})来创建递归正则表达式.一个例子可以在
perlre – Extended Patterns找到.
以下是在 our $braces_re; $braces_re = qr{ { (?: (?> [^{}]+ ) | (??{ $braces_re }) )* } }sx; # parse FOO block while ( $data =~ m{ ^FOO s+ (w+) s* { ( (?: [^{}]+ | (??{ $braces_re }) )* ) # Matched braces only. } }mgx ) { my $params = $1; # parse BAR block next if $params !~ m{ BAR s* { ( (?: [^{}]+ | (??{ $braces_re }) )*? ) # Matched braces only. } }mx; # SOME CODE } 注意,我故意将_re变量的声明和它的初始化分开.有一些perl版本可以让你在与初始化相同的语句中声明一个递归正则表达式,但v5.8.9不是其中之一. 此外,如果您只是简单地替换(?PARNO)符号来改变原始正则表达式,那么上述内容可以简化为以下内容.也于 my $braces_re; $braces_re = qr{ (?: (?> [^{}]+ ) | # The following is a "postponed" regular subexpression. { (??{ $braces_re }) } # Deferred execution enables recursive regex )* }sx; # parse FOO block while ( $data =~ m{^FOO s+ (w+) s* { ( $braces_re ) } }mgx ) { my $params = $1; # parse BAR block next if $params !~ m{BAR s* { ( $braces_re ) }}mx; # SOME CODE } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |