Break out of replace global loop

做~自己de王妃 提交于 2021-01-28 01:33:44

问题


I have a RegExp, doing a string replace, with global set. I only need one replace, but I'm using global because there's a second set of pattern matching (a mathematical equation that determines acceptable indices for the start of the replace) that I can't readily express as part of a regex.

var myString = //function-created string
myString = myString.replace(myRegex, function(){
    if (/* this index is okay */){

        //!! want to STOP searching now !!//
        return //my return string

    } else {
        return arguments[0];
        //return the string we matched (no change)
        //continue on to the next match
    }
}, "g");

If even possible, how do I break out of the string global search?

Thanks

Possible Solution

A solution (that doesn't work in my scenario for performance reasons, since I have very large strings with thousands of possible matches to very complex RegExp running hundreds or thousands of times):

var matched = false;
var myString = //function-created string
myString = myString.replace(myRegex, function(){
    if (!matched && /* this index is okay */){
        matched = true;
        //!! want to STOP searching now !!//
        return //my return string

    } else {
        return arguments[0];
        //return the string we matched (no change)
        //continue on to the next match
    }
}, "g");

回答1:


Use RegExp.exec() instead. Since you only do replacement once, I make use of that fact to simplify the replacement logic.

var myString = "some string";
// NOTE: The g flag is important!
var myRegex = /some_regex/g;

// Default value when no match is found
var result = myString;
var arr = null;

while ((arr = myRegex.exec(myString)) != null) {
    // arr.index gives the starting index of the match
    if (/* index is OK */) {
        // Assign new value to result
        result = myString.substring(0, arr.index) +
                 /* replacement */ +
                 myString.substring(myRegex.lastIndex);
        break;
    }

    // Increment lastIndex of myRegex if the regex matches an empty string
    // This is important to prevent infinite loop
    if (arr[0].length == 0) {
        myRegex.lastIndex++;
    }
}

This code exhibits the same behavior as String.match(), since it also increments the index by 1 if the last match is empty to prevent infinite loop.




回答2:


You can put try-catch and use undeclared variable to exit the replace function

var i = 0;

try{
 "aaaaa".replace ( /./g, function( a, b ){

  //Exit the loop on the 3-rd iteration
  if ( i === 3 ){

   stop; //undeclared variable

  }

  //Increment i
  i++

 })

}
catch( err ){
}

alert ( "i = " + i ); //Shows 3



回答3:


I question your logic about performance. I think some points made in the comments are valid. But, what do I know... ;)

However, this is one way of doing what you want. Again, I think this, performance wise, isn't the best...:

var myString = "This is the original string. Let's see if the original will change...";
var myRegex = new RegExp('original', 'g');
var matched=false;

document.write(myString+'<br>');

myString = myString.replace(myRegex, function (match) {

    if ( !matched ) {

        matched = true;
        return 'replaced';

    } else {
        return match;
    }
});

document.write(myString);

It's pretty much like your "Possible Solution". And it doesn't "abort" after the replace (hence my performance reservation). But it does what you asked for. It replaces the first instance, sets a flag and after that just returns the matched string.

See it work here.

Regards.



来源:https://stackoverflow.com/questions/21435986/break-out-of-replace-global-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!