regex - Extracting multiple subsections of a file in Perl -
i have following script , want turn parts of perl script. parts i'm interested in similar perl , easy convert (fyi: cond
, formula
mean if
, return
in perl, respectively). however, i'm struggling extract these sections properly.
... #other stuffs k k1 { ... #more other stuffs 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) } } ... #more other stuffs } ... #other stuffs k k2 { ... #more other stuffs 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) } } ... #more other stuffs } ... #other stuffs k k3 { ... #more other stuffs 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) } } ... #more other stuffs } ... #other stuff
i've tried following perl-liner,
perl -ne 'print $1 if /k\sk2\s\{/ .. /\}/ , /lol\s\{/ .. /\}/ , /cond*(.*)/' filename
to extract, instance, { d < 0.03 }
from
k k2 { ... #more other stuffs 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) } } ... #more other stuffs }
but
- it failed , don't know how fix
- how can fix in way able catch second
cond
statement in same section (i.e.cond { w >= 0.03 }
). in other word, how can skip first, second,... occurrence of string.
ps if can extraction part done, know how convert perl-looking code
parse conditions, , translate them anonymous subroutines can eval'd , assigned hash.
you want test below thoroughly before using, don't know full data set.
use strict; use warnings; our %formula_per_k; init { # list functions want allow in formulas. other words interpretted variables. @formula_funcs = qw(sqrt exp log); # load data via file. $data = {local $/; <data>}; # parse k blocks while ($data =~ m{ ^k \s+ (\w+) \s* \{ ( (?: [^{}]+ | \{(?2)\} )* ) # matched braces only. \} }mgx) { ($name, $params) = ($1, $2); # parse lol block next if $params !~ m{ lol \s* \{ ( (?: [^{}]+ | \{(?1)\} )*? ) # matched braces only. \} }mx; $lol = $1; # start building anonymous subroutine $conditions = ''; # parse conditions , formulas while ($lol =~ m{ cond \s* \{ (.*?) \} \s* formula \s* \{ (.*?) \} }gx) { ($cond, $formula) = ($1, $2); # remove excess spacing , translate variable perl scalar. ($cond, $formula) { s/^\s+|\s+$//g; s{([a-za-z]+)}{ $var = $1; $var = "\$hashref->{$var}" if ! grep {$var eq $_} @formula_funcs; $var }eg; } $conditions .= "return $formula if $cond; "; } $code = "sub {my \$hashref = shift; ${conditions} return; }"; $sub = eval $code; if ($@) { die "invalid formulas in $name: $@"; } $formula_per_k{$name} = $sub; } } sub formula_per_k { ($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
outputs:
'k1', {d => .1} = 2.13345237791561 'k1', {d => .05} = 2.01370729772479 'k3', {d => .02} = -4.13029437251523 'k3', {d => .021} = -4.13002941430942
Comments
Post a Comment