16

javascriptで正規表現を使用して、文字列から可能なすべての一致を取得しようとしています。これを行う私の方法は、すでに一致した文字列の一部と一致していないようです。

変数:

var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';

var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;

コード:

var match = string.match(reg);

私が得るすべての一致した結果:

A1B1Y:A1B2Y
A1B5Y:A1B6Y
A1B9Y:A1B10Y

一致した結果:

A1B1Y:A1B2Y
A1B2Y:A1B3Y
A1B5Y:A1B6Y
A1B6Y:A1B7Y
A1B9Y:A1B10Y
A1B10Y:A1B11Y

文字列内では 2 つの一致の一部である必要がありますが、私の頭の中ではA1B1Y:A1B2Y、 と一緒に一致したいと考えてA1B2Y:A1B3Yいます。A1B2Y

4

3 に答える 3

25

.exec正規表現を変更せずに、正規表現オブジェクトのlastIndexプロパティを使用および操作することで、各マッチの後、マッチの後半の開始時にマッチを開始するように設定できます。

var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';
var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;
var matches = [], found;
while (found = reg.exec(string)) {
    matches.push(found[0]);
    reg.lastIndex -= found[0].split(':')[1].length;
}

console.log(matches);
//["A1B1Y:A1B2Y", "A1B2Y:A1B3Y", "A1B5Y:A1B6Y", "A1B6Y:A1B7Y", "A1B9Y:A1B10Y", "A1B10Y:A1B11Y"]

デモ


Bergi のコメントによると、最後の試合のインデックスを取得して 1 ずつインクリメントすることもできるため、試合の後半から試合を開始するのではなく、各試合の 2 番目の文字から試合を開始します。 :

reg.lastIndex = found.index+1;

デモ

最終的な結果は同じです。ただし、Bergi の更新ではコードが少し少なくなり、実行速度がわずかに速くなります。=]

于 2013-02-13T21:14:33.570 に答える
4

から直接結果を取得することはできませんが、正規表現を変更してmatch結果を生成することは可能です。RegExp.exec

var regex = /A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g;
var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y'
var arr;
var results = [];

while ((arr = regex.exec(input)) !== null) {
    results.push(arr[0] + arr[1]);
}

テキストを消費しないようにゼロ幅の正の先読みを使用(?=pattern)して、重複部分を再照合できるようにしました。

実際には、replaceメソッドを悪用して同じ結果を得ることができます。

var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y'
var results = [];

input.replace(/A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g, function ($0, $1) {
    results.push($0 + $1);
    return '';
});

ただ、replace中古なので余計な無駄な交換作業をします。

于 2013-02-13T21:15:32.557 に答える
3

残念ながら、それは単一のstring.match.

その理由は、/gフラグが提供しないオーバーラップマッチが必要だからです。

先読みを使用できます:

var re = /A\d+B\d+Y(?=:A\d+B\d+Y)/g;

しかし今、あなたは得る:

string.match(re); // ["A1B1Y", "A1B2Y", "A1B5Y", "A1B6Y", "A1B9Y", "A1B10Y"]

その理由は、先読みがゼロ幅であるためです。つまり、一致させようとしているものの後にパターンが来るかどうかを示しているだけです。マッチには含まれません。

exec必要なものを試してつかむために使用できます。正規表現に/gフラグがある場合、exec繰り返し実行してすべての一致を取得できます。

// using re from above to get the overlapping matches

var m;
var matches = [];
var re2 = /A\d+B\d+Y:A\d+B\d+Y/g; // make another regex to get what we need

while ((m = re.exec(string)) !== null) {
  // m is a match object, which has the index of the current match
  matches.push(string.substring(m.index).match(re2)[0]);
}

matches == [
  "A1B1Y:A1B2Y", 
  "A1B2Y:A1B3Y", 
  "A1B5Y:A1B6Y", 
  "A1B6Y:A1B7Y", 
  "A1B9Y:A1B10Y", 
  "A1B10Y:A1B11Y"
];

これが実際のフィドルです。コンソールを開いて結果を確認する

または、元の文字列を で分割し、結果の配列をループして、必要なときに一致するものと両方:が一致するものを引き出すことができます。array[i]array[i+1]

于 2013-02-13T21:28:19.433 に答える