开发者

How to know if JavaScript string.replace() did anything?

开发者 https://www.devze.com 2023-02-15 19:02 出处:网络
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开发者_JAVA百科 know whether it actual

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开发者_JAVA百科 know whether it actually replaced anything apart from comparing the result with the original string?


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 '!';});


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.


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]


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.


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);


While this will require multiple operations, using .test() may suffice:

const regex = /foo/;
const yourString = 'foo bar';

if (regex.test(yourString)) {
  console.log('yourString contains regex');
  // Go ahead and do whatever else you'd like.
}

The test() method executes a search for a match between a regular expression and a specified string. Returns true or false.


With indexOf you can check wether a string contains another string.
Seems like you might want to use that.


have a look at string.match() or string.search()


After doing any RegExp method, read RegExp.lastMatch property:

/^$/.test('');  //Clear RegExp.lastMatch first, Its value will be ''

'abcd'.replace(/bc/,'12');

if(RegExp.lastMatch !== '')
  console.log('has been replaced');
else
  console.log('not replaced');
0

精彩评论

暂无评论...
验证码 换一张
取 消