0

I wanna make a function in javascript

function replaceAll(str, find, replaceBy)

that replaces all occurrences of a specified word in a string, if an occurrence is surrounded by whitespace (/s/ - not just " ".). In addition it is okay, if an occurrence is at the beginning of the string (but has whitespace on the rightside), or if the occurrence is the last word (but has whitespace on its leftside).

I've tried to do a while loop, but it got very ugly. I believe this is doable with some intelligent regex, though I'm not really skilled with regular expressions.

Sample input

replaceAll("I went down to the III  Isupermarket. I never<I>  go  anywhere outside my \n  house   I", "I", "he");

Sample output

"he went down to the III  Isupermarket. he never<I>  go  anywhere outside my \n  house   he"

Any help much apreciated! Thanks

  • you could just write code that finds the occurrences of target string `find` inside `str` and then individually test the characters before and after those substring's indices – Ennui Feb 25 '14 at 22:01
  • http://stackoverflow.com/questions/1144783/replacing-all-occurrences-of-a-string-in-javascript/1144788#1144788 – Sean Bright Feb 25 '14 at 22:01

1 Answers1

2

You can construct a regex that allows for the whitespace on either side:

function replaceAll(str, find, replaceBy) {
    var regex = new RegExp("(^|\\s)" + find + "(?=\\s|$)", "g");
    return str.replace(regex, "$1" + replaceBy);
}

Working demo: http://jsfiddle.net/jfriend00/dC5T7/


Then, to escape the characters in the find string and replaceBy string before using it as part of regex, you can do this:

RegExp.escapePattern = function(s) {
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};

RegExp.escapeReplace = function(s) {
    return s.replace(/\$/g, "$$");
};

function replaceAll(str, find, replaceBy) {
    find = RegExp.escapePattern(find);
    replaceBy = RegExp.escapeReplace(replaceBy);
    var regex = new RegExp("(^|\\s)" + find + "(?=\\s|$)", "g");
    return str.replace(regex, "$1" + replaceBy);
}

Working demo of the two escape operations: http://jsfiddle.net/jfriend00/xV9e8/

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I believe it returns 'heI went down to the III Isupermarket. I never go anywhere outside my \n house I' for the example I provided – askemottelson Feb 25 '14 at 22:08
  • @hrsorensen - check out this jsFiddle: http://jsfiddle.net/jfriend00/dC5T7/. It seems to give you the desired output exactly. – jfriend00 Feb 25 '14 at 22:13
  • yup - going to accept this one. didn't notice the other proposals accidentally matched to . – askemottelson Feb 25 '14 at 22:38
  • but again, I'd like to know if the find parameter should be escaped? thanks! – askemottelson Feb 25 '14 at 22:38
  • This is more correct than using `\b`. Verified in the Chrome console with OP's sample input/output. – Justin Morgan - On strike Feb 25 '14 at 22:39
  • 1
    @hrsorensen - as I answered your comment above, you would need to escape `find` if it may contain regex characters. Even `replaceBy` would have an issue with the `$` special replacement chars. – jfriend00 Feb 25 '14 at 22:40
  • @hrsorensen - I added a version that escapes both the `find` and `replaceBy` arguments. – jfriend00 Feb 26 '14 at 03:24
  • if you run replaceAll("house house house", "house", "basement"); you get --> "basement house basement" ??? – askemottelson Mar 19 '14 at 16:15
  • @hrsorensen - quite honestly, it's hard to know what your full specification is and what all interesting test cases you want it to work for are. You can try this one: http://jsfiddle.net/jfriend00/W4Fu8/. – jfriend00 Mar 19 '14 at 16:38
  • @jfriend00 : I'm sorry if the definition was too unclear, but I just now realised that it didn't work for two occurences next to each other. I believe that my initial "that replaces all occurrences of a specified word in a string, if an occurrence is surrounded by whitespace" specified that. But once again, you incrediblt fast an accurately saves my day. thank you! – askemottelson Mar 19 '14 at 16:43
  • can you explain me why the previous didn't work? the middle 'house' in "house house house", is surrounded by whitespace – askemottelson Mar 19 '14 at 16:52
  • 1
    @hrsorensen - Because once the first whitespace is used by the first replace operation, it isn't considered for future matches so the middle match wouldn't have leading whitespace and wouldn't match. This is what the `\b` feature is supposed to be used for, but your requirement of actual whitespace, not just what a regex thinks is a word boundary makes it so we can't use `\b` as the other answers that tried `\b` found out. There's probably a way to use non-capturing whitespace in the regex, but what I ended up with was simpler. – jfriend00 Mar 19 '14 at 17:05
  • 1
    @hrsorensen - here's a bit better version that uses lookahead matching http://jsfiddle.net/jfriend00/BjCkK/ – jfriend00 Mar 19 '14 at 17:20