Reputation: 32207
Regex test()
is giving me issues in Firefox and Chrome, yet it works flawlessly in Opera and Safari.
troubled code:
var pattern = /(\s+(?!\$\w+)|(^(?!\$\w+)))/g;
if(pattern.test(String(id).replace(/\s+OR|AND\s+/g, ''))) {
searchError("You suck.");
return 1;
}
When you pass in white space, it blocks it every time. When you pass in something like '$a b'
then it will work every other time in Firefox/Chrome. WEIRD.
Upvotes: 46
Views: 11016
Reputation: 1736
for some reason, matchAll()
works correctly even though test()
doesnt
Upvotes: 0
Reputation: 338
Update: 9/27/23 - I am STILL running into this issue.
Consider the following:
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(Validators.pattern(new RegExp(validator.value)));
break;
where each validator is an object I've defined on our server like so (for example):
{
"name": "lowercaseandunderscore"
"value": "^[a-z_]*$",
"type": "pattern",
"error": "Column names must only contain lower case letters and underscores"
}
Now, one would assume this would inherently work using reactive forms, but it does not! It falls into the same pit as the post in 2021 below. Don't be fooled!
I came across this today.
Oddly, what works is the following:
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(Validators.pattern(new RegExp(/^[a-z_]*$/)));
break;
This does not fail every other time!
But, if you are creating a Regex from using the class, using a STRING... watch out. You'll have to do something like this.
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(this.testValue(validator));
break;
where your testValue function is the following:
private testValue(validator: any): ValidatorFn {
return (control: AbstractControl) => {
let returnVal = null;
if(control.value){
//NOTE the use of parenthesis around the RegExp below.
if((new RegExp(validator.value, 'gm').test(control.value))){
return null;
} else {
return {[validator.name]: validator.error};
}
}
return returnVal;
}
}
As I was working through this today, I honestly thought "surely I can't be facing that same exact problem with regexes...". Turns out, I was.
There is something to be said for every time you create a RegExp with a string. Just wrap it in parenthesis. For whatever reason, creating it without a string literal works like it should.
I hope this hammers that point home.
Essentially, regexes seem to misbehave when created from string literals, and seem to be just fine when created NOT from a string.
///End of update
This seems to still be an issue in August of 2021... I just want to share some things I have learned before stumbling upon this question and answer. I was baffled by this problem and had no meaningful way forward - until now.
It doesn't matter whether you use exec()
or test()
or match()
. The regex still doesn't work properly on every other occurrence.
It doesn't matter if you set the regex with
let reg = new RegExp(/<table(\s*[^>]*)>/g);
or with const
. Doesn't matter if you set it globally or locally either...
What does work to bypass this problem is wrapping your regex statement in parenthesis in your loop like so:
Object.keys(table).forEach(key => {
if((new RegExp(/<table(\s*[^>]*)>/g)).test(___your test string___)){
//Do what you need to do
}
});
Remove the parenthesis around the Regex, and watch every other one fail....
Thank you so much for the answer @Nick Craver and the comment @prototype!
This exact Regex was what was giving me trouble. It would work for one object, and fail for the subsequent object, and it made no sense. I am only here to say that this is still very relevant in 2021.
Upvotes: 6
Reputation: 630379
It's a bug in the RegEx engine, a similar question with the same issue came up here.
From my answer to that question: It's a bug with the way regexes are implemented in ECMAScript 3, there's a great post on the details here.
The basics are a /regex/
with the g
modifier doesn't reset correctly, so multiple .test()
calls alternate between true
and false
if everyone should be true
, every other calls successfully resets it.
Upvotes: 97