2013-06-22 113 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