0

I have the following string:

"i like ??dogs? and cats"

I want to identify the substring ??dogs? and replace it for something else, let's say "?birds".

So I created this function to do it:

function strUnderline (str, oldword, newword) {
                    str = str.replace(new RegExp('(^|[-,.!?:;"\'\(\\s])' + oldword + '(?=$|[-?!,.:;"\'\)\\s])'), "$1" + newword)
            return str;
        };

But when I run:

strUnderline("i like ??dogs? and cats", "??dogs?", "?birds")

i get:

"i like ???birds? and cats"

I want to define word boundaries and also capture them.

Any suggestions?

GalAbra
  • 5,048
  • 4
  • 23
  • 42
N.Car
  • 492
  • 1
  • 4
  • 14
  • Please tag a language. – Mitya May 30 '18 at 18:17
  • See https://jsfiddle.net/vn8o3pev/, I do not think you need a word boundary here. – Wiktor Stribiżew May 30 '18 at 19:58
  • @WiktorStribiżew thank you for your reply. the purpose of word boundaries is to avoid something like "strUnderline("i like ??dogs? and cats", "dogs", "?birds")" returning "i like ???birds? and cats" it should only replace if the whole "word" including the characters attached is found – N.Car May 30 '18 at 20:10
  • Then please explain what is a word boundary for you. Whitespaces and start/end of the string? Or any word chars? – Wiktor Stribiżew May 30 '18 at 20:13
  • yes, spaces, start end and some other chars like hyphen, etc. sorry for leaving that out :) – N.Car May 30 '18 at 20:14
  • Well, it is not that clear. See https://jsfiddle.net/vn8o3pev/1/ - a version with whitespace boundaries. – Wiktor Stribiżew May 30 '18 at 20:15
  • Yes! It works! Could you please explain what's happening in your regular expressions? – N.Car May 31 '18 at 21:41

1 Answers1

2

If you want to replace all the occurrences of a oldWord, you need to escape the question marks:

function strUnderline(str, oldWord, newWord) {
  oldWord = oldWord.replace(new RegExp(/\?/g), "\\?");
  return str.replace(new RegExp(oldWord, 'g'), newWord);
}

let input = "i like ??dogs? and cats, but especially ??dogs?";
let output = strUnderline(input, "??dogs?", "?birds");
console.log(output);

For a more general regex, that escapes all special characters, read this.

GalAbra
  • 5,048
  • 4
  • 23
  • 42
  • the problem with that is if I have an array of substrings to replace in the original, some of them might not even be a word. example: "i like ham and i am hungry" . if i replace "am" for "are" it'll end up like "i like hare and i am hungry" – N.Car May 30 '18 at 19:11
  • @N.Car then surround the word with wordboundaries \b. They mark the transition between a \w and a \W. But not as usefull with characters as the question mark, since that's a non-word character. – LukStorms May 30 '18 at 19:20
  • Btw, note that a replace that's not using a regex with the g flag only replaces the first occurence. – LukStorms May 30 '18 at 19:24
  • I've edited my answer, even though @LukStorms is right - without the global flag, a regex would replace only first occurrence as well – GalAbra May 30 '18 at 20:48
  • 1
    Hi! this seems to work perfectly! Could you explain exactly what's happening in the second line of the solution youve come up with? – N.Car May 31 '18 at 21:40
  • 1
    @N.Car Thanks a lot! When using regular expressions, some characters are reserved for meta-regex commands. One of them is the question mark, and therefore it needs to be escaped (`\?` instead of `?`). You can read more thoroughly about it [here](https://www.regular-expressions.info/refcharacters.html). Glad I could help! – GalAbra May 31 '18 at 21:45