> I have created a simple test, which compares results of native > perl s/// (via eval) and proposed template 'replace' vmethod.
After thinking a bit, I understand that trying to recreate perl s/// behavior in details is a bad idea. I think that reasonable level of details is simulating perl's $1, $2 etc backreferences, with possibility to escape $ with backslash, and to escape backslash itself before $1 (etc). So I throw out \1, \2 tests from my vmeth_replace.t and added some other tests. You can find it here: http://martynoff.info/tt2/ Here is my version of 'replace' vmethod, which satisfies the test: 'replace' => sub { my ($text, $pattern, $replace, $global) = @_; my ($matched, $after, @start, @end); my $result = ''; $global = 1 unless defined $global; while ($text =~ m/$pattern/) { if($#- == 0) { # no captured groups so do a simple search and replace if($global) { $text =~ s/$pattern/$replace/g } else { $text =~ s/$pattern/$replace/ } last; } # extract the bit before the match, the match itself, the # bit after and the positions of all subgroups $result .= substr($text, 0, $-[0]) if $-[0]; $after = substr($text, $+[0]); @start = @-; @end = @+; # first, collect all matched groups to array my @backrefs; for (my $i = 0; $i < @start; $i++) { push @backrefs, substr( $text, $start[$i], $end[$i] - $start[$i] ); } # just replace whole match :) $matched = $replace; # replace the $1, $2, etc. placeholders # in reverse order (to ensure we do $10 before $1) $matched =~ s{ \\(\\|\$) # an escaped backslash (\\) or $ sign (\$) | \$(\d+) # backreference }{ $1 || $backrefs[$2] }gxoe; # add the modified $matched output to the result and loop if global $result .= $matched; $text = $after; last unless $global && length $text; } return $result . $text; }, (It is also available in separate file) -- Sergey Martynoff _______________________________________________ templates mailing list [email protected] http://lists.template-toolkit.org/mailman/listinfo/templates
