如何在Regex中使前缀和捕获的字符可选?

时间:2016-08-01 13:31:53

标签: regex

给出以下字符串,

var str = "<%= stylesheet_link_tag 'project/theme-one', media: 'all' if @auth.show?  %>"

在regex下面返回一个有效的匹配

str.match(/\<%= stylesheet_link_tag\s+['"]?(.*)['"],.+if(.*)%\>/)

// [
//  "<%= stylesheet_link_tag 'project/theme-one', media: 'all' if @auth.show?  %>", 
//  "project/theme-one", 
//  " @auth.show?  "
// ]

但是,它失败并带有以下字符串(没有if条件):

var str = "<%= stylesheet_link_tag 'project/theme-one', media: 'all' %>"

// Expected result
// [
//  "<%= stylesheet_link_tag 'project/theme-one', media: 'all' if @auth.show?  %>", 
//  "project/theme-one", 
//  " "
// ]

如何让if(.*)部分正则表达式可选?

2 个答案:

答案 0 :(得分:2)

通常,要使某些模式可选(即匹配1或0次),您需要使用?量词。如果您有一个符号,则可以在其后附加?。如果您有一系列子模式,最好的方法是将它们放入非捕获组(?:...)并在其后添加?

您可以使用

<%= stylesheet_link_tag\s+['"]?(.*?)['"],.+?(?:if(.*))?%>
                                  ^        ^^^^^^^^^^^^  

请参阅regex demo

这里的重点是第一个.+过于贪婪,并且选择了(?:if(.*))?部分。 .+应该与+?一起变得懒惰。此外,要稍微优化模式,您还需要在['"]?['"]之间使用延迟点匹配。

JS演示:

var re = /<%= stylesheet_link_tag\s+['"]?(.*?)['"],.+?(?:if(.*))?%>/g; 
var str = '<%= stylesheet_link_tag \'project/theme-one\', media: \'all\' if @auth.show?  %>\n<%= stylesheet_link_tag \'project/theme-one\', media: \'all\' %>';

var res0 = [];
 var res1 = [];
 var res2 = [];
 
while ((m = re.exec(str)) !== null) {
 res0.push(m[0]);
 res1.push(m[1]);
 res2.push(m[2]);
}
console.log(res0);
console.log(res1);
console.log(res2);

答案 1 :(得分:0)

(if.*)*应该可以正常工作。完整的正则表达式:\<%= stylesheet_link_tag\s+['"]?(.*)['"],.+(if(.*))*%\>

Test