Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does RegEx.test changes the result in subsequent calls? [duplicate]

Why does the following go from true to false;

var r = /e/gi;
r.test('e'); // true
r.test('e'); // false

and then it continue switching true, false, true, false ......

like image 529
Edwin Reynoso Avatar asked Mar 07 '15 03:03

Edwin Reynoso


People also ask

How does regex matcher work?

A regex engine executes the regex one character at a time in left-to-right order. This input string itself is parsed one character at a time, in left-to-right order. Once a character is matched, it's said to be consumed from the input, and the engine moves to the next input character.

Does regex affect performance?

Being more specific with your regular expressions, even if they become much longer, can make a world of difference in performance. The fewer characters you scan to determine the match, the faster your regexes will be.

Is regex matching fast?

Regular expression matching can be simple and fast, using finite automata-based techniques that have been known for decades. In contrast, Perl, PCRE, Python, Ruby, Java, and many other languages have regular expression implementations based on recursive backtracking that are simple but can be excruciatingly slow.

Does regex match anything?

In regular expressions, we can match any character using period "." character. To match multiple characters or a given set of characters, we should use character classes.


1 Answers

Its because of the g flag. It starts remembering the last index of the match and when you do r.test next time, it starts from that index. That is why it alternates between true and false. Try this

var r = /e/gi;
console.log(r.test('e'));
# true
console.log(r.lastIndex);
# 1
console.log(r.test('e'));
# false
console.log(r.lastIndex);
# 0
console.log(r.test('e'));
# true
console.log(r.lastIndex);
# 1
console.log(r.test('e'));
# false

Quoting MDN Documentation on RegExp.lastIndex,

The lastIndex is a read/write integer property of regular expressions that specifies the index at which to start the next match. ...

This property is set only if the regular expression used the "g" flag to indicate a global search. The following rules apply:

  1. If lastIndex is greater than the length of the string, test() and exec() fail, then lastIndex is set to 0.
  2. If lastIndex is equal to the length of the string and if the regular expression matches the empty string, then the regular expression matches input starting at lastIndex.
  3. If lastIndex is equal to the length of the string and if the regular expression does not match the empty string, then the regular expression mismatches input, and lastIndex is reset to 0.
  4. Otherwise, lastIndex is set to the next position following the most recent match.

The bold text above answers the behaviour you observed. After the first match, e, the lastIndex is set to 1, to indicate the index from which the next match should be tried. According to the 3rd point seen above, since the lastIndex is equal to the length of the string and the regular expression doesn't match the empty string, it returns false and resets lastIndex to 0.

like image 154
thefourtheye Avatar answered Sep 22 '22 03:09

thefourtheye