2013-06-22 85 views
3

因此,目前,我的代码适用于包含一组圆括号的输入。Javascript - 正则表达式寻找多个圆括号匹配

var re = /^.*\((.*\)).*$/; 
var inPar = userIn.replace(re, '$1'); 

...当用户输入的化学式的Cu(NO3)2,警报inPar返回NO3),我想的意思。然而,如果Cu(NO3)2(CO2)3是输入物,则只有CO2)被返回。

我在RegEx中不太知道,为什么会发生这种情况,并且有没有办法让NO3)和CO2)在发现后进入数组?

回答

11

你想使用String.match而不是String.replace。你还希望你的正则表达式在括号中匹配多个字符串,所以你不能有^(字符串的开始)和$(字符串的结尾)。在括号内匹配时,我们不能贪婪,所以我们将使用。*?

通过改变步进,我们得到:

// Use Match 
"Cu(NO3)2(CO2)3".match(/^.*\((.*\)).*$/); 
["Cu(NO3)2(CO2)3", "CO2)"] 

// Lets stop including the) in our match 
"Cu(NO3)2(CO2)3".match(/^.*\((.*)\).*$/); 
["Cu(NO3)2(CO2)3", "CO2"] 

// Instead of matching the entire string, lets search for just what we want 
"Cu(NO3)2(CO2)3".match(/\((.*)\)/); 
["(NO3)2(CO2)", "NO3)2(CO2"] 

// Oops, we're being a bit too greedy, and capturing everything in a single match 
"Cu(NO3)2(CO2)3".match(/\((.*?)\)/); 
["(NO3)", "NO3"] 

// Looks like we're only searching for a single result. Lets add the Global flag 
"Cu(NO3)2(CO2)3".match(/\((.*?)\)/g); 
["(NO3)", "(CO2)"] 

// Global captures the entire match, and ignore our capture groups, so lets remove them 
"Cu(NO3)2(CO2)3".match(/\(.*?\)/g); 
["(NO3)", "(CO2)"] 

// Now to remove the parentheses. We can use Array.prototype.map for that! 
var elements = "Cu(NO3)2(CO2)3".match(/\(.*?\)/g); 
elements = elements.map(function(match) { return match.slice(1, -1); }) 
["NO3", "CO2"] 

// And if you want the closing parenthesis as Fabrício Matté mentioned 
var elements = "Cu(NO3)2(CO2)3".match(/\(.*?\)/g); 
elements = elements.map(function(match) { return match.substr(1); }) 
["NO3)", "CO2)"] 
+0

打浆到时钟。 +1指出匹配而不是替换和全局修饰符 –

+0

从这个问题来看,我认为'''结束符'应该在返回的字符串中。此外,我宁愿'match.slice(1,-1)'去除开始和结束括号,而不是将不必要的正则表达式放入它。 –

+0

切片上的好电话!我会更新代码来使用它。我不确定为什么Rygh2014会这么做),但是在你的代码和我的代码之间,这应该是一个相当明显的变化。 – SpenserJ

3

您的正则表达式具有匹配字符串开头和结尾的锚点,因此它不足以匹配多个匹配项。使用String.match与正则表达式g标志(全球改性剂)更新代码:

var userIn = 'Cu(NO3)2(CO2)3'; 
var inPar = userIn.match(/\([^)]*\)/g).map(function(s){ return s.substr(1); }); 
inPar; //["NO3)", "CO2)"] 

如果你需要旧IE支持:Array.prototype.map polyfill

或者不polyfills:

var userIn = 'Cu(NO3)2(CO2)3'; 
var inPar = []; 
userIn.replace(/\(([^)]*\))/g, function(s, m) { inPar.push(m); }); 
inPar; //["NO3)", "CO2)"] 

以上匹配的(和捕获一系列零个或多个非)字符,然后是)并将其推送到inPar阵列。

第一个正则表达式基本上是相同的,但是使用整个匹配,包括开头的(圆括号(稍后通过映射数组除去),而不是捕获组。


从我承担收盘)括号预计将在生成的字符串的问题,否则,这里有没有右括号更新的解决方案:(使用s.slice(1, -1)

对于第一种解决方案:

var inPar = userIn.match(/\([^)]*\)/g).map(function(s){ return s.slice(1, -1);}); 

对于第二溶液(\)捕获组以外):

userIn.replace(/\(([^)]*)\)/g, function(s, m) { inPar.push(m); }); 
0

你可以试试下面的:

"Cu(NO3)2".match(/(\S\S\d)/gi) // returns NO3 


"Cu(NO3)2(CO2)3".match(/(\S\S\d)/gi) // returns NO3 CO2