1

I have this paragraph:

<p>FIRST SECOND THIRD</p>

and I want to wrap the second word in a SPAN like so:

<p>FIRST <span>SECOND</span> THIRD</p>

If I do this:

text.replace(/\s(\w+)\s/, '<span>$1</span>');

the space characters before and after the word disappear. Why? What am I doing wrong? I thought /\s(\w+)\s/ captures the word but not the spaces.

See here: http://jsfiddle.net/simevidas/TpTzV/

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385

3 Answers3

3

The spaces are stripped away because they're part of the entire match. The capture is what it remembers to substitute back into the replacement string via backreferences.

If JavaScript supported both lookahead and lookbehind assertions you could do this:

text.replace(/(?<\s)(\w+)(?=\s)/, '<span>$1</span>');

But it doesn't, so you can try capturing the spaces (separately from the word you're wrapping) and putting them back in instead:

text.replace(/(\s)(\w+)(\s)/, '$1<span>$2</span>$3');
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • @Bolt So `$1` represents the entire match and not the first capturing parentheses? – Šime Vidas Apr 30 '11 at 22:53
  • `$1` represents the first capture. The entire match is denoted by [`$&`](http://stackoverflow.com/questions/4688730/what-does-in-str-replacespecials-mean/4688753#4688753). – BoltClock Apr 30 '11 at 22:55
  • @Bolt But the entire match is going to be replaced with the string, not just the first capture. That's where I got it wrong... – Šime Vidas Apr 30 '11 at 22:56
  • @Šime Vidas: Yup, that's why you capture the spaces along with the word and put them all back in. – BoltClock Apr 30 '11 at 23:00
  • The lookahead/behind regex would work because the matches wouldn't be "consumed" -- so won't be a part of the match. It's a shame Javascript doesn't support these kind of regexes, they are useful in many occasions. – Gary Green May 07 '11 at 14:01
1

$1 will be the part captured by the bit you have wrapped in parentheses, which is \w+, which will consist of word characters and not spaces. If you want to capture the spaces too, do this:

/(\s\w+\s)/
Trott
  • 66,479
  • 23
  • 173
  • 212
  • That'd result in ` SECOND `, with the spaces within the tags. – BoltClock Apr 30 '11 at 23:00
  • 1
    That's what I thought you wanted, for whatever reason. If you want the spaces outside the tags, then you need either three different captures (one for each space and one for the word, which appears to be the answer you've accepted) or you need to insert the spaces in your replace like this: text.replace(/\s(\w+)\s/, ' $1 '); Note that that last one will replace whatever whitespace character is on either side of the word with a space. But if that doesn't matter to you, then that will do it. – Trott Apr 30 '11 at 23:09
  • Note that the original comment to your answer is not from me `:)`. – Šime Vidas Apr 30 '11 at 23:48
1

Spaces disapear because is not grouped.

Try with:

replace(/(\s\w+\s)/

Spaces (\s) inside the grouping.

jotapdiez
  • 1,456
  • 13
  • 28