I thought this would have been an "no-brainer" addition to my regEx, but of course I was proven wrong...
My current regEx returns true if the string is a symbol (-, $, +, =, (, ), {, }):
(/^[-$+)(}{]$/).test(token);
I want to add two symbols to the regEx, the assignment operator (=), and the equality operator (==). My intuition guided me to do something along the lines of to return true if there exists a token with one or two '=':
(/^[-$+)(}{]|(=){1,2}$/).test(token);
but yet if the actual token is (/^[-$+)(}{]|(=){1,2}$/).test("===") true is returned.
Can someone shed some light on my regEx shortcomings?
Thanks
You've run into a subtle operator precedence problem.
/^[-$+)(}{]|(=){1,2}$/
^ and $ bind more tightly than |, so this is equivalent to
/(?:^[\-$+)(}{])|(?:={1,2}$)/
instead of what you probably want which is to have ^...$ enclose the |:
/^(?:[\-$+)(}{]|={1,2})$/
or simplified
/^(?:[\-$+(){}]|==?)$/
/^(?:[\-$+(){}]|==?)$/.test("===") === false;
/^(?:[\-$+(){}]|==?)$/.test("()") === false;
/^(?:[\-$+(){}]|==?)$/.test("=") === true;
/^(?:[\-$+(){}]|==?)$/.test("==") === true;
/^(?:[\-$+(){}]|==?)$/.test("(") === true;
I prefer (?:...) to (...) unless I actually want to capture content because, although (?:...) is more verbose, it has fewer subtle effects on code that uses the regular expression.
Some problems with using capturing groups when you don't intend to capture content include:
exec loop,
(This is mostly a problem with perlish global matches like @foo = $str =~ /(foo(bar))/g
but every once in a while you'll see JS code doing something similar)
newStr = oldStr.replace(
regexDefinedEarlier,
function (var_args) {
return [].slice.call(arguments, 1, arguments.length - 2).join('');
});
Because of operator precedence, the or branches include the start (^) and end ($) zero-width matches. To catch = or ==, you'd have to use:
(/^([-$+)(}{]|={1,2})$/).test(token);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With