2016-03-06 76 views
0

我有一个简单的脚本来匹配系列剧集代码,如S01E02s09e11。这个想法是找到提供的文本中的所有插曲代码,并创建一个包含所有发现节目的对象数组。正则表达式“gi”修饰符的组合不适用于单个单词

我首先使用match()来获取所有匹配代码的数组,然后我通过代码循环来提取季节和剧集编号。

问题是,当我用同样的正则表达式图案既寻找所有比赛,并提取情节细节/gi改性剂,我得到一个错误:Uncaught TypeError: Cannot read property '1' of null(参见控制台输出)。

案例1(不及格) - fiddle 1

var episodePatternGI = /s(\d{1,2})e(\d{1,2})/gi; 
var matches = 'S3E1 hehehe bla s09e12'.match(episodePatternGI); 
var episodes = []; 

matches.forEach(function(val) { 
    var ep = episodePatternGI.exec(val); 
    episodes.push({ 
    s: ep[1], 
    e: ep[2] 
    }); 
}); 

console.log(episodes); 

案例2(工作) - fiddle 2

var episodePatternGI = /s(\d{1,2})e(\d{1,2})/gi; 
var matches = 'S3E1 hehehe bla s09e12'.match(episodePatternGI); 
var episodes = []; 

var episodePatternI = /s(\d{1,2})e(\d{1,2})/i; // g modifier removed 

matches.forEach(function(val) { 
    var ep = episodePatternI.exec(val); // New pattern applied 
    episodes.push({ 
    s: ep[1], 
    e: ep[2] 
    }); 
}); 

console.log(episodes); 

正如你所看到的,在第二case我使用相同的模式,但g修改器被删除。

为什么第一种情况不起作用?

回答

3

的问题是,lastIndex不会自动重置了,所以,当你调用exec的第二场比赛,也不会开始寻找在字符串的开头,因此它不会匹配。

您可以将其设置为0手动复位lastIndex

var episodePatternGI = /s(\d{1,2})e(\d{1,2})/gi; 
var matches = 'S3E1 hehehe bla s09e12'.match(episodePatternGI); 
var episodes = matches.map(function(val) { 
    episodePatternGI.lastIndex = 0; 
    var ep = episodePatternGI.exec(val); 
    return { 
    s: ep[1], 
    e: ep[2] 
    }; 
}); 
console.log(episodes); 

调用exec,直到到达字符串的结尾(第2个电话应该是足够了),如图anubhava's answer,将重置lastIndex太。

+0

准确地说我正在寻找答案。 – lesssugar

+1

噢,你打我答案。我正要提交 – 4castle

+2

尽管如此,实际上可能会使用lastIndex来获得优势,只需循环exec()直到它返回null。因为目前正则表达式的使用量是其需要量的两倍。跳过匹配数组部分。 – 4castle

2

你必须在一个循环中使用regexp.exec抢拍摄组同时使用g标志:

var episodePatternGI = /s(\d{1,2})e(\d{1,2})/gi; 
var str = 'S3E1 hehehe bla s09e12'; 
var episodes = []; 

var m; 
while ((m = episodePatternGI.exec(str)) !== null) { 
    episodes.push({ 
     s: m[1], 
     e: m[2] 
     }); 
} 

console.log(episodes); 

Updated Fiddle

RegEx Demo(检查代码生成在这个环节)

+0

好的,我明白了。基本上我需要在每次迭代期间手动跟踪'exec()'索引。有点讨厌;)谢谢! – lesssugar

+0

但是,我没有得到的东西是,在我的代码中,我正在循环访问代码数组,并且分别从每个代码**中提取季节和情节**。然而,exec()'索引在某种程度上是全球性的?带'while'的解决方案有点不同,更简洁。 “forEach”一个 - 不工作 - 困扰着我。 – lesssugar

+0

事实上,在这种情况下并不是真的需要,现在看到更新的答案。 – anubhava

0

如果你想将多个标志传递给JS中的RegExp,你也可以这样做:

var episodePatternGI = /s(\d{1,2})e(\d{1,2})/; 
var other = new RegExp(episodePatternGI.source, "gi"); 

这里是一个相关主题:Changing the RegExp flags