views:

250

answers:

2

I am trying to wrap some words with HTML tags, for that I am using regular expressions. I am almost there:

This is my regexp

/((apple|banana|cherry|orange)\b\s?)+/gi

and this is my replacement:

<em>$&</em>

which works perfectly for my example text:

Apple Banana apple cherry, Cherry orange and Oranges Apple, Banana

the result being:

<em>Apple Banana apple cherry</em>, <em>Cherry orange </em>and Oranges <em>Apple</em>, <em>Banana</em>

I could be pragmatic and live with this but I would reaaaaaally like to have it perfect and not include the space after the final match.

i.e. my perfect result would be (see the tag shifted left after "Cherry orange"):

<em>Apple Banana apple cherry</em>, <em>Cherry orange</em> and Oranges <em>Apple</em>, <em>Banana</em>
+1  A: 

Hi,

You could put function in the replace parameter as

function(x){return "<em>"+x.replace(/\s+$/,"")+"<em>";} instead of <em>$&</em>

and you could put striping space inside that function.

"Apple Banana apple cherry, Cherry orange and Oranges Apple, Banana".replace(
/((?:apple|banana|cherry|orange)\b\s?)+/gi,
function(x){
   return "<em>"+x.replace(/\s+$/,"")+"<em>";
})

<em>Apple Banana apple cherry<em>, <em>Cherry orange<em>and Oranges <em>Apple<em>, <em>Banana<em>
S.Mark
+1, didn't see how to this in a one-liner
Am
Could you please elaborate how come the second argument for replace is a function? I can't find any documentation about this behavior.
LiraNuna
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace - but attention, it is not supported by all browsers (IE5, for example)
nalply
not too bad but slightly less elegant. ;-)
Kris
+3  A: 

JavaScript doesn't support lookbehind. This is a shame, as we could have done:

// doesn't work in JavaScript:
/((apple|banana|cherry|orange)\b\s?)+(?<!\s)/gi

What we can do, however, is to move the white-space to the beginning, and add a negative lookahead (so the catch must not start with a white-space):

/(?!\s)(\s?\b(apple|banana|cherry|orange)\b)+/gi

A slight difference from your code is that I also added \b to the beginning of the pattern, so it wouldn't catch apple from Snapple.

Kobi
JavaScript does not have issues with lookbehind, it doesn't support it. Perhaps this is what you meant, but "has issues" suggests (to me) that it *does* support it, but the implementation contains bugs.
Bart Kiers
I know, that is what I meant. That's a **big issue**. I agree, Bart, I'll change it to avoid confusion.
Kobi
the `\b` didn't seem to be necessary in my original example.Awesome thanks!! This was my first question on StackOverflow. I am absolutely amazed I got a perfect answer this quick!
Kris
No problem, Thanks! Welcome to StackOverflow. BTW, it's a very good question, and well formatted. Probably the reason it was up voted that much.
Kobi