web-dev-qa-db-ja.com

Javascriptで2つの文字列の間の文字列を取得するための正規表現

私は非常によく似た投稿を見つけましたが、私の正規表現をここで得ることはできません。

私は他の2つの文字列の間にある文字列を返す正規表現を書き込もうとしています。たとえば、次のようにします。文字列 "cow"と "milk"の間にある文字列を取得します。

私の牛はいつも牛乳をくれる

戻る

「いつでも」

これが私がこれまでにつなぎ合わせた表現です。

(?=cow).*(?=milk)

しかし、これは文字列 "cow always gives"を返します

127
phil

先読み(その(?=部分)は入力を消費しません。これは幅ゼロのアサーションです(境界チェックと後書きも同様です)。

cowの部分を消費するには、ここで通常の一致が必要です。その間の部分をキャプチャーするには、キャプチャー・グループを使用します(キャプチャーしたいパターンの部分を括弧内に入れてください)。

cow(.*)milk

先読みはまったく必要ありません。

149

Javascriptで2つの文字列の間の文字列を取得するための正規表現

ほとんどの場合にうまくいく最も完全な解決策は、キャプチャグループlazy dot matchingを使うことです。パターンただし、JS正規表現のドット.は改行文字と一致しないため、100%の場合に機能するのは[^]または[\s\S]/[\d\D]/[\w\W]の構文です。

ECMAScript 2018以降の互換ソリューション

ECMAScript 2018をサポートするJS環境では、sname__修飾子は.が改行文字を含む任意の文字と一致することを可能にし、regexエンジンは可変長の後書きをサポートします。だから、あなたはのような正規表現を使用することができます

var result = s.match(/(?<=cow\s+).*?(?=\s+milk)/gs); // Returns multiple matches if any
// Or
var result = s.match(/(?<=cow\s*).*?(?=\s*milk)/gs); // Same but whitespaces are optional

どちらの場合も、cowname__の後に1/0以上の空白があるcowname__について現在位置がチェックされ、その後、可能な限り少ない0+文字が一致して消費され(=一致値に追加され)、milkname__がチェックされます。 (このサブストリングの前に1/0以上の空白がある場合)。

シナリオ1:単一行入力

これ以降のシナリオはすべてのJS環境でサポートされています。答えの下部にある使用例を参照してください。

cow (.*?) milk

最初にcowname__が見つけられ、次にスペース、そして*?が怠惰な量指定子である限りできるだけ少ない改行以外の0+文字がグループ1に取り込まれ、それからmilkname__を伴うスペースが続く必要があります。 消費されました

シナリオ2:複数行入力

cow ([\s\S]*?) milk

ここでは、最初にcowname__とスペースがマッチングされ、次に、可能な限り少ない0+文字がマッチングされてグループ1に取り込まれ、次にmilkname__を持つスペースがマッチングされます。

シナリオ3:重複する試合

>>>15 text>>>67 text2>>>のような文字列があり、その間に>>> + numbername __ + whitespacename__と>>>の間で2つの一致を取得する必要がある場合、 />>>\d+\s(.*?)>>>/g を使用することはできません。 >>>より前の67は、最初の一致が見つかった時点ですでに消費されています。あなたはそれを実際に「ぐらつかせる」ことなくテキストの存在をチェックするために 前向きな先読み を使うことができます(すなわちマッチに追加する) :

/>>>\d+\s(.*?)(?=>>>)/g

グループ1の内容が見つかった場合の online regex demo y yield text1およびtext2を参照してください。

文字列について可能性のあるすべての重なり合う一致を取得する方法 も参照してください。

パフォーマンスの考慮事項

非常に長い入力が与えられると、正規表現パターン内の遅延ドットマッチングパターン(.*?)はスクリプトの実行を遅くするかもしれません。多くの場合、 ループを展開する手法 が役立ちます。 "Their\ncow\ngives\nmore\nmilk"からcowname__とmilkname__の間をすべて取得しようとすると、milkname__で始まらないすべての行と一致させる必要があることがわかります。したがって、 cow\n([\s\S]*?)\nmilk の代わりに使用できます。

/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm

regex demo を参照してください(\r\nがある場合は、/cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gmを使用してください)。この小さなテスト文字列ではパフォーマンスの向上はごくわずかですが、非常に大きなテキストでは違いがわかります(特に行が長く改行がそれほど多くない場合)。

JavaScriptでの正規表現の使用例

//Single/First match expected: use no global modifier and access match[1]
console.log("My cow always gives milk".match(/cow (.*?) milk/)[1]);
// Multiple matches: get multiple matches with a global modifier and 
// trim the results if length of leading/trailing delimiters is known
var s = "My cow always gives milk, thier cow also gives milk";
console.log(s.match(/cow (.*?) milk/g).map(function(x) {return x.substr(4,x.length-9);}));
//or use RegExp#exec inside a loop to collect all the Group 1 contents
var result = [], m, rx = /cow (.*?) milk/g;
while ((m=rx.exec(s)) !== null) {
  result.Push(m[1]);
}
console.log(result);
52

これは牛と牛乳の間にあるものをつかむ正規表現です(前後のスペースなしで):

srctext = "My cow always gives milk.";
var re = /(.*cow\s+)(.*)(\s+milk.*)/;
var newtext = srctext.replace(re, "$2");

例: http://jsfiddle.net/entropo/tkP74/

49
entropo
  • .*をキャプチャする必要があります
  • あなたは.*を不一致にすることができます(しかしそうする必要はありません)
  • 先読みの必要はまったくありません。

    > /cow(.*?)milk/i.exec('My cow always gives milk');
    ["cow always gives milk", " always gives "]
    
15
Matt Ball

以下のMartinho Fernandesのソリューションを使用して、必要なものを入手できました。コードは次のとおりです。

var test = "My cow always gives milk";

var testRE = test.match("cow(.*)milk");
alert(testRE[1]);

TestRE変数を配列として警告していることに気付くでしょう。これは、何らかの理由でtestREが配列として返すためです。からの出力:

My cow always gives milk

変更点:

always gives
6
phil

選ばれた答えは私のために働かなかった…うーん….

牛の後や牛乳の前にスペースを追加して、「常に与える」からスペースを削除するだけです。

/(?<=cow ).*(?= milk)/

enter image description here

5
duduwe

次の正規表現を使うだけのことです。

(?<=My cow\s).*?(?=\smilk)
2
Brandon

メソッドmatch()は、文字列から一致するものを検索し、Arrayオブジェクトを返します。

// Original string
var str = "My cow always gives milk";

// Using index [0] would return<br/>
// "**cow always gives milk**"
str.match(/cow(.*)milk/)**[0]**


// Using index **[1]** would return
// "**always gives**"
str.match(/cow(.*)milk/)[1]
0
Marc Antoni