Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How do i find $a and replace it with $b when it's preceded by $c?

( #17840=categorized question: print w/ replies, xml ) Need Help??
Contributed by whahoo on Jun 13, 2000 at 08:42 UTC
Q&A  > regular expressions


Answer: How do i find $a and replace it with $b when it's preceded by $c?
contributed by nuance

A postivive look behind clause in the regular expression will do what you want.

my($a, $b, $c, $d) = qw{foo bar moo moofooyou); $d =~ s/(?<=$c)$a/$b/g;
produces moobaryou in $d
Answer: How do i find $a and replace it with $b when it's preceded by $c?
contributed by Roy Johnson

If $c is actually a pattern, you should use the lookbehind. If you're just dealing with strings, the fastest might be some work with substr/index.

use Benchmark; use vars qw/$a $b $c/; ($a, $b, $c) = qw/bar baz foo/; timethese(shift || 500000, { lookbehind => sub { local $_ = "foobarquux"; s/(?<=$c)$a/$b/g +}, chromatic => sub { local $_ = "foobarquux"; s/($c)$a/$1$b/g +}, chromatic2 => sub { local $_ = "foobarquux"; s/$c$a/$c$b/g }, substr => sub { local $_ = "foobarquux"; while ((my $p = index($_, "$c$a"))>=0) { substr($_, $p+length($c), length($a), $b); } }, });
Output:
chromatic: 11 wallclock secs (10.67 usr + 0.00 sys = 10.67 CPU) @ 46 +860.36/s (n=500000) chromatic2: 10 wallclock secs ( 8.81 usr + 0.00 sys = 8.81 CPU) @ 56 +753.69/s (n=500000) lookbehind: 10 wallclock secs ( 9.42 usr + 0.00 sys = 9.42 CPU) @ 53 +078.56/s (n=500000) substr: 4 wallclock secs ( 3.98 usr + 0.00 sys = 3.98 CPU) @ 12 +5628.14/s (n=500000)
Answer: How do i find $a and replace it with $b when it's preceded by $c?
contributed by btrott

<Editor's Note:>
Here is chromatic's post to which btrott is responding.

I prefer a simpler approach:

s/$c$a/$c$b/g; or s/($c)$a/$1$b/g;
Am I missing anything the lookbehind provides?

</Editor's Note>

All right... here's a benchmark of the two methods (lookbehind and just straight substitution). It looks like lookbehind is slightly faster, but not by a huge lot. Here's the code:

use Benchmark; use vars qw/$a $b $c/; ($a, $b, $c) = qw/bar baz foo/; timethese(shift || 1, { lookbehind => sub { local $_ = "foobarquux"; s/(?<=$c)$a/$b/g +}, chromatic => sub { local $_ = "foobarquux"; s/($c)$a/$1$b/g +}, });
And here are the benchmark results:
Benchmark: timing 500000 iterations of chromatic, lookbehind... chromatic: 15 wallclock secs (14.46 usr + 0.00 sys = 14.46 CPU) lookbehind: 13 wallclock secs (11.93 usr + 0.00 sys = 11.93 CPU)
Answer: How do i find $a and replace it with $b when it's preceded by $c?
contributed by Incognito

To summarize what's been done by chromatic, btrott and nuance, with the chromatic version using no backreferences named chromatic2, we have:

Benchmark: timing 500000 iterations of chromatic, chromatic2, lookbehi +nd... chromatic: 18 wallclock secs (18.83 usr + 0.01 sys = 18.84 CPU) @ 265 +43.50/s chromatic2: 13 wallclock secs (13.55 usr + 0.00 sys = 13.55 CPU) @ 369 +00.37/s lookbehind: 14 wallclock secs (14.95 usr + 0.00 sys = 14.95 CPU) @ 334 +42.58/s
for the test:
use Benchmark; use vars qw/$a $b $c/; ($a, $b, $c) = qw/bar baz foo/; timethese(shift || 500000, { lookbehind => sub { local $_ = "foobarquux"; s/(?<=$c)$a/$b/g +}, chromatic => sub { local $_ = "foobarquux"; s/($c)$a/$1$b/g +}, chromatic2 => sub { local $_ = "foobarquux"; s/$c$a/$c$b/g } +, });
Answer: How do i find $a and replace it with $b when it's preceded by $c?
contributed by Anonymous Monk

I did a benchmark, and the fastest solution is s/$c$a/$c$b/g. Don't use backreferences unless you have to.

Please (register and) log in if you wish to add an answer



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others romping around the Monastery: (9)
    As of 2014-12-21 18:12 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      Is guessing a good strategy for surviving in the IT business?





      Results (106 votes), past polls