The replace
function returns the new string with the replaces, but if there weren't any words to replace, then the original string is returned. Is there a way to know whether it actually replaced anything apart from comparing the result with the original string?
问题:
回答1:
A simple option is to check for matches before you replace:
var regex = /i/g;
var newStr = str;
var replaced = str.search(regex) >= 0;
if(replaced){
newStr = newStr.replace(regex, '!');
}
If you don't want that either, you can abuse the replace
callback to achieve that in a single pass:
var replaced = false;
var newStr = str.replace(/i/g, function(token){replaced = true; return '!';});
回答2:
Comparing the before and after strings is the easiest way to check if it did anything, there's no intrinsic support in String.replace()
.
[contrived example of how '==' might fail deleted because it was wrong]
回答3:
As a workaround you can implement your own callback function that will set a flag and do the replacement. The replacement
argument of replace
can accept functions.
回答4:
If your replace has a different length from the searched text, you can check the length of the string before and after. I know, this is a partial response, valid only on a subset of the problem.
OR
You can do a search. If the search is successfull you do a replace on the substring starting with the found index and then recompose the string. This could be slower because you are generating 3 strings instead of 2.
var test = "Hellllo";
var index = test.search(/ll/);
if (index >= 0) {
test = test.substr(0, index - 1) + test.substr(index).replace(/ll/g, "tt");
}
alert(test);
回答5:
Javascript replace
is defected by design. Why? It has no compatibility with string replacement in callback.
For example:
"ab".replace(/(a)(b)/, "$1$2")
> "ab"
We want to verify that replace is done in single pass. I was imagine something like:
"ab".replace(/(a)(b)/, "$1$2", function replacing() { console.log('ok'); })
> "ab"
Real variant:
"ab".replace(/(a)(b)/, function replacing() {
console.log('ok');
return "$1$2";
})
> ok
> "$1$2"
But function replacing
is designed to receive $0, $1, $2, offset, string
and we have to fight with replacement "$1$2". The solution is:
"ab".replace(/(a)(b)/, function replacing() {
console.log('ok');
// arguments are $0, $1, ..., offset, string
return Array.from(arguments).slice(1, -2)
.reduce(function (pattern, match, index) {
// '$1' from strings like '$11 $12' shouldn't be replaced.
return pattern.replace(
new RegExp("\\$" + (index + 1) + "(?=[^\\d]|$)", "g"),
match
);
}, "$1$2");
});
> ok
> "ab"
This solution is not perfect. String replacement itself has its own WATs. For example:
"a".replace(/(a)/, "$01")
> "a"
"a".replace(/(a)/, "$001")
> "$001"
If you want to care about compatibility you have to read spec and implement all its craziness.
回答6:
With indexOf
you can check wether a string contains another string.
Seems like you might want to use that.
回答7:
have a look at string.match() or string.search()