I would actually use lookbehind and lookahead to make the replacement simpler:
s,(?<!\w)($worda)(\W+)($wordb)(?!\w),<B>$1</B>$2<B>$3</B>,i
Next, I'm trying to figure out what makes s|<B><B>|<B>|g; s|</B></B>|</B>|g; necessary. Because your regex only allows non-word characters between word A and word B, and <B> and </B> each contain a word character, once bold tags are put around a word that word should never be matched by your regex again. Ah... Unless your material may already contain some bold tags before you do any of the substitutions. Then you could end up with doubled tags to remove.
Finally, here's how I would try to do this more efficiently. I would combine @material into a single string, perform the substitutions, and then split back to @material.
As you can see, I'm using "\0" as a temporary divider between pieces of @material; I've updated the regex to make sure matches don't overlap two pieces.my $material = join "\0", @material; foreach $phrase (@key_phrases) { my($worda, $wordb) = split / /, $phrase; $material =~ s{(?<!\w)($worda)([^\w\0]+)($wordb)(?!\w)} {<B>$1</B>$2<B>$3</B>}i; } @material = split /\0/, $material;
I considered also building a single regex to match all the key phrases, but since each phrase appears only once I don't know if that would be more efficient.
In reply to Re: foreach (@array) s/x/y/ efficiency
by chipmunk
in thread foreach (@array) s/x/y/ efficiency
by gryphon
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |