Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: How to do regex backreferences within $variable replacement text?

by Tanktalus (Canon)
on Sep 17, 2005 at 21:41 UTC ( [id://492927]=note: print w/replies, xml ) Need Help??


in reply to How to do regex backreferences within $variable replacement text?

Here's some example code on how to do this with a few tests. I'd invite adding some more tests and any bug reports/security issues as I've not really thought about this from a security perspective yet. It's a bit slower in that it matches twice, but it completely avoids any eval.

use strict; use warnings; sub substitute { my ($string, $from, $to) = @_; $from = qr/$from/ unless ref $from and ref $from eq 'Regexp'; my @a = $string =~ $from; $to =~ s/\$(\d+)/$a[$1-1]/g; # was $to =~ s/\$(\d+)/\Q$a[$1-1]/g; $string =~ s/$from/$to/; $string; } my @tests = ( [ "this is some test", "(is) s(o)me", '$1 n$2t a' ], [ "this is some test", "is some", 'is not a' ], ); for my $t (@tests) { print "[$t->[0]]..."; print "[",substitute(@$t), "]\n"; }
prints out:
[this is some test]...[this is not a test] [this is some test]...[this is not a test]
which is what I expected. But, as you can see, it's not a very extensive test, so feel free to try a few more.

Update: It turns out that the \Q in the $to replacement wasn't needed.

Replies are listed 'Best First'.
Re^2: How to do regex backreferences within $variable replacement text?
by ManFromNeptune (Scribe) on Sep 18, 2005 at 03:12 UTC
    Ok, this appears to be working, except for one thing: for the backreferenced sections, spaces are getting prepended with a backslash in the $to clause, and subsequently in the $string. Here's a test I added:
    [ 'Once upon a time, Jack Roush was not the king of the NASCAR garage, + but a stock-car outsider from Michigan trying to start a Winston Cup + team with a small-time budget.', '(king of the NASCAR )(garage, but +a stock-car)', 'HERE1$1HERE2$2HERE3' ]
    And here's the output:
    [Once upon a time, Jack Roush was not the king of the NASCAR garage, b +ut a stock-car outsider from Michigan trying to start a Winston Cup t +eam with a small-time budget.] ... [Once upon a time, Jack Roush was not the HERE1king\ of\ the\ NASCAR\ +HERE2garage\,\ but\ a\ stock\-carHERE3 outsider from Michigan trying +to start a Winston Cup team with a small-time budget.]

    Any ideas? I can't see where these backslashes are coming from...!
Re^2: How to do regex backreferences within $variable replacement text?
by ikegami (Patriarch) on May 10, 2006 at 21:57 UTC

    When allowing the emdedding of code (loosely defined), provide an escape mechanism!!! For example,

    • I have no means of replacing with $1 . "00". Perl uses "${1}00".
    • I have no means of replacing with '$1.00'. Perl uses the literal "\$1.00".

    When adding your escape mechanism, careful not to break existing functionality. For example,

    • Continue allowing me to replace with '\$1'. Perl uses "\\$1".

    Update: A solution is to replace

    $to =~ s/\$(\d+)/$a[$1-1]/g;

    with

    $to =~ s/\\(.)|\${(\d+)})|\$(\d+)/ (defined $1 ? $1 : (defined $2 ? $a[$2-1] : $a[$3-1] ) ) /eg;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://492927]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-26 06:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found