正则表达式重复字母虚假和真实?

时间:2017-07-17 02:37:53

标签: javascript regex

我有一个字符串数组,我试图过滤包含重复字母的字符串数组。然而,有两件奇怪的事情正在发生,我不明白。这是我的代码:

var array = ["aba", "aab", "baa"];

var pattern = /(\D)\1+/gi;

var filteredArr = array.filter(function(element){
    console.log(element);
    console.log(pattern.test(element));
    return pattern.test(element) != true;
});

console.log(filteredArr);

发生了一些奇怪的事情。在filter函数中,我测试正则表达式是真还是假,并且它应该如此。

pattern.test("aba") = false;
pattern.test("aab") = true;
pattern.test("baa") = true;

但是,如果我在函数之外测试它们,“baa”似乎会返回false ...这很奇怪吧?

console.log(pattern.test("aba")); //returns false
console.log(pattern.test("aab")); //returns true
console.log(pattern.test("baa")); //returns false

进入下一个奇怪的事情。过滤器函数应该返回不通过(即返回false)过滤器测试的元素。我的预期输出是:

filteredArr = ["aba"];

但是,按照代码的方式,我的输出是:

filteredArr = ["aba", "aab", "baa"];

更奇怪的是,如果我更改过滤器函数以返回DO传递的元素(即返回true)测试,则预期的输出将是:

filteredArr = ["aab", "baa"];

但是,我收到的输出是一个空数组:

filteredArr = [];

我非常困惑。我的正则表达式是错误的还是我可能尝试过滤功能无法做到的事情?这是所有代码的小提琴:

My fiddle

3 个答案:

答案 0 :(得分:2)

您看到的奇怪行为是g修饰符的结果。每次调用test都会提升模式的lastIndex属性,这使得对test()的下一次调用从字符串中的稍后点开始。

这是MDN description of the lastIndex property

  

仅当正则表达式实例使用时才设置此属性   “g”标志表示全局搜索。以下规则适用:

     
      
  • 如果lastIndex大于字符串的长度,test()exec()失败,则lastIndex设置为0
  •   
  • 如果lastIndex等于字符串的长度,并且正则表达式与空字符串匹配,那么正则表达式   匹配从lastIndex开始的输入。
  •   
  • 如果lastIndex等于字符串的长度,并且正则表达式与空字符串不匹配,那么常规   表达式不匹配输入,lastIndex重置为0
  •   
  • 否则,lastIndex将设置为最近一次匹配后的下一个位置。
  •   

您可以通过将console.log(pattern.lastIndex);添加到filter

来验证这一点

var array = ["aba", "aab", "baa"];

var pattern = /(\D)\1+/gi;

var filteredArr = array.filter(function(element){
  var test = pattern.test(element);
  console.log(element + ": " + test);
  console.log(pattern.lastIndex);
  return test;
});

console.log(filteredArr);

要修复代码,请从正则表达式中删除g标记。

答案 1 :(得分:0)

您正在使用.test的全局正则表达式,这是有问题的。

考虑以下开发控制台跟踪

$ var pattern = /(\D)\1+/gi;
undefined
$ pattern.lastIndex
0
$ pattern.test('xx')
true
$ pattern.lastIndex
2
$ pattern.test('xx')
false
$ pattern.lastIndex
0

您遇到的问题是在RegExpg标志继续检查lastIndex,因此如果您连续两次检查相同的字符串,则会得到不同的结果。

您可以手动重置pattern.lastIndex = 0或使用非全局RegExp

答案 2 :(得分:0)

这是一个有效的例子。



var array = ["aba", "aab", "baa","bba","bab"];


var filteredArr = array.filter(function(element){
    console.log(element);
    //note that a constant is used instead of the var
    var t = /(\D)\1+?/gi.test(element);
    console.log(t);
    return !t;
});

console.log(filteredArr);




您的代码存在问题:

  

每当您想知道是否在a中找到模式时,请使用test()   string(类似于String.prototype.search()方法,区别在于   test()返回一个布尔值,而search()返回索引(或   -1如果没有找到);有关更多信息(但执行速度较慢),请使用exec()方法(类似于String.prototype.match()方法)。如   使用exec()(或与之结合使用),test()多次调用   在同一个全局正则表达式实例将超过   上一场比赛

RegExp.prototype.test()