regex.test() 只能每隔一次工作

问题描述 投票:0回答:3

Regex

test()
在 Firefox 和 Chrome 中给我带来了问题,但它在 Opera 和 Safari 中完美运行。

有问题的代码:

var pattern = /(\s+(?!\$\w+)|(^(?!\$\w+)))/g;
if(pattern.test(String(id).replace(/\s+OR|AND\s+/g, ''))) {
 searchError("You suck.");
 return 1;
}

当你通过空白区域时,它每次都会挡住它。当您传入类似

'$a b'
之类的内容时,它会在 Firefox/Chrome 中每隔一段时间工作一次。奇怪。

javascript regex firefox google-chrome safari
3个回答
96
投票

这是正则表达式引擎中的一个错误,这里出现了具有相同问题的类似问题

从我对这个问题的回答来看:这是 ECMAScript 3 中实现正则表达式的方式的一个错误,这里有一篇关于详细信息的很棒的文章

基础知识是带有

/regex/
修饰符的
g
无法正确重置,因此多个
.test()
调用会在
true
false
之间交替,如果每个人 should 都是
true
,则所有其他调用都会成功重置它。


5
投票

更新:23 年 9 月 27 日 - 我仍然遇到这个问题。

考虑以下因素:

  1. 您正在使用 Angular 反应式表单,并且正在使用一些内置功能,例如开箱即用的验证器。
  2. 您使用类似以下内容。
      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;

其中每个验证器都是我在服务器上定义的对象,如下所示(例如):

{
"name": "lowercaseandunderscore"
"value": "^[a-z_]*$",
"type": "pattern",
"error": "Column names must only contain lower case letters and underscores"
}

现在,人们会认为这本质上可以使用反应形式来工作,但事实并非如此!和下面2021年的帖子掉进了同一个坑。别被骗了!

我今天遇到了这个。

奇怪的是,有效的方法如下:

      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;

这不会每次都失败!

但是,如果您通过使用类、使用 STRING 创建正则表达式...请注意。你必须做这样的事情。

      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;

您的 testValue 函数如下:

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

当我今天解决这个问题时,我真诚地想“我肯定不会遇到正则表达式同样的问题......”。事实证明,我是。

每次使用字符串创建 RegExp 时,都有一些事情要说。只需将其括在括号中即可。无论出于何种原因,在不使用字符串文字的情况下创建它都可以正常工作。

我希望这能击中要害。

从本质上讲,正则表达式在从字符串文字创建时似乎表现不佳,而在不从字符串创建时似乎表现得很好。

///更新结束

这似乎在 2021 年 8 月仍然是一个问题......我只想分享我在偶然发现这个问题和答案之前学到的一些东西。我对这个问题感到困惑,并且没有任何有意义的前进方向 - 直到现在。

  1. 无论您使用

    exec()
    还是
    test()
    match()
    都没有关系。正则表达式在其他所有情况下仍然无法正常工作。

  2. 使用

    设置正则表达式并不重要
let reg = new RegExp(/<table(\s*[^>]*)>/g);

或与

const
。无论您在全局还是本地设置它都没有关系......

绕过这个问题的所做的工作是将正则表达式语句包装在循环中的括号中,如下所示:

Object.keys(table).forEach(key => {
    if((new RegExp(/<table(\s*[^>]*)>/g)).test(___your test string___)){
        //Do what you need to do
    }
});

删除正则表达式周围的括号,然后观察其他每个都失败......

非常感谢@Nick Craver 的回答和@prototype 的评论!

正是这个正则表达式给我带来了麻烦。它对一个对象有效,但对后续对象无效,而且没有任何意义。我在这里只是想说,这在 2021 年仍然非常相关


0
投票

由于某种原因,

matchAll()
可以正常工作,尽管
test()
不能

© www.soinside.com 2019 - 2024. All rights reserved.