3

所以目前,我的代码适用于包含一组括号的输入。

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

...意思是当用户输入化学式 Cu(NO3)2 时,提醒 inPar 返回 NO3) ,这是我想要的。

但是,如果 Cu(NO3)2(CO2)3 是输入,则仅返回 CO2)。

我对 RegEx 不太了解,所以为什么会发生这种情况,有没有办法在找到 NO3) 和 CO2) 后将它们放入数组中?

4

3 回答 3

12

您想使用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)"]
于 2013-06-22T02:55:53.110 回答
3

您的正则表达式具有匹配字符串开头和结尾的锚点,因此它不足以匹配多次出现。String.match使用RegExpg标志(全局修饰符)更新代码:

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.mappolyfill

或者没有 polyfill:

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

上面匹配 a(并捕获零个或多个非)字符的序列,然后是 a)并将其推送到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); });
于 2013-06-22T02:47:21.003 回答
0

您可以尝试以下方法:

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


"Cu(NO3)2(CO2)3".match(/(\S\S\d)/gi)   // returns NO3  CO2
于 2013-06-22T07:47:25.580 回答