3

したがって、現在、私のコードは、1 組の括弧を含む入力に対して機能します。

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

...つまり、ユーザーが化学式 Cu(NO3)2 を入力すると、アラート inPar が NO3) を返します。

ただし、Cu(NO3)2(CO2)3 が入力の場合は、CO2) のみが返されます。

私は正規表現についてあまり詳しくないので、なぜこれが起こっているのですか?また、NO3) と CO2) を見つけた後に配列に入れる方法はありますか?

4

3 に答える 3

12

String.replaceの代わりに String.matchを使用します。また、正規表現が括弧内の複数の文字列と一致するようにする必要があるため、^ (文字列の開始) と $ (文字列の終了) を使用することはできません。また、括弧内で一致させる場合は貪欲になることはできないため、.*? を使用します。

変更をステップ実行すると、次のようになります。

// 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.matchRegExpgフラグ (グローバル修飾子)を使用して更新されたコード:

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

またはポリフィルなし:

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

上記は a に一致し、(0 個以上の非)文字のシーケンスをキャプチャし、その後に a が続き、)それを配列にプッシュしinParます。

(最初の正規表現は本質的に同じことを行いますが、キャプチャ グループの代わりに左括弧 (後で配列をマッピングすることによって削除されます)を含む一致全体を使用します。


質問から、閉じ括弧が結果の文字列にあると予想されると仮定し)ます。それ以外の場合は、閉じ括弧のない更新されたソリューションを次に示します。

最初のソリューションの場合 (を使用s.slice(1, -1)):

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

2 番目のソリューション (\)キャプチャ グループの外側) の場合:

userIn.replace(/\(([^)]*)\)/g, function(s, m) { inPar.push(m); });
于 2013-06-22T02:47:21.003 に答える