问题
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