0

Suppose I have a string like this:

my favorite berry is the blueberry, not the strawberry or berryfruit

I want to find all instances of berry and blueberry where each is an isolated word, as opposed to a substring of a longer word, and change each into the other, to get this result:

my favorite blueberry is the berry, not the strawberry or berryfruit

Naturally, I can't just do this:

str=str.replace(/blueberry/g,"berry");
str=str.replace(/berry/g,"blueberry");

because that will just change all the "berry" substrings to "blueberry".

I've tried the following code:

<div id="displayDiv"></div>
<script type="text/javascript">

    function replaceSeparateInstances(inputStr,findStr,replaceStr){

        var re=new RegExp("^"+findStr+"(?!\w)|^"+findStr+"$|[\\W\\s]"+
                    findStr+"(?!\w)|[\\W\\s]"+findStr+"$","g");

        return inputStr.replace(re,replaceStr);
    }

    function berryBlueberrySwap(inputStr){
        var result=replaceSeparateInstances(inputStr,"blueberry","abc");
        result=replaceSeparateInstances(result,"berry","xyz");      
        result=result.replace(/abc/g,"berry");
        result=result.replace(/xyz/g,"blueberry");
        return result;

    }

    var div=document.getElementById("displayDiv");
    var content="my favorite berry is the blueberry, not the strawberry or berryfruit";
    div.textContent=berryBlueberrySwap(content);
</script>

There are several problems with this:

  • The spaces are being removed from the left of words replaced by replaceSeparateInstances() because there's no negative lookbehind in Javascript. I've seen some of the SO posts on how to do a workaround for this but I can't figure out how to apply them for purposes of a replace().

  • This solution relies on changing the two strings into temp strings "abc" and "xyz", which is a problem if these strings actually exist in the text.

  • The "berry" in "berryfruit" is getting found by the regex, and it shouldn't be found because the "f" to the right of "berry" is a \w character.

Is there a better way to do this?

EDIT: I tried using the function described at the duplicate link, as follows:

function switchInstances(inputStr,findStr1,findStr2){

        var findStr="("+findStr1+"|"+findStr2+")";

        var re=new RegExp("^"+findStr+"(?!\w)|^"+findStr+"$|[\\W\\s]"+
                    findStr+"(?!\w)|[\\W\\s]"+findStr+"$","g");
        console.log(re.source);

        return inputStr.replace(re,function($1){
            return $1===findStr1 ? findStr2 : findStr1});
    }

function berryBlueberrySwap(inputStr){

        var result=switchInstances(inputStr,"berry","blueberry");
        return result;      

 }

But that generated this output:

my favoriteberry is theberry, not the strawberry orberryfruit

So I still have the problem of the lookbehinds, and now the "berry" isn't being changed into "blueberry".

sigil
  • 9,370
  • 40
  • 119
  • 199

0 Answers0