String.replace 関数の悪用
関数を使ってちょっとしたトリックを使いreplace
ます。関数は一致をループし、replace
関数を指定できるため、可能性は無限大です。結果は になりますoutput
。
var output = [];
var str = "Mary had a little lamb";
str.replace(/[A-Za-z]+(?=(\s[A-Za-z]+))/g, function ($0, $1) {
output.push($0 + $1);
return $0; // Actually we don't care. You don't even need to return
});
出力には入力文字列の重複部分が含まれるため、先読み 1を使用して現在の単語を照合するときに、次の単語を消費しないようにする必要があります。
正規表現/[A-Za-z]+(?=(\s[A-Za-z]+))/g
は、私が上で述べたこととまったく同じように動作します: 部分 (正規表現の開始) で一度に 1 つの単語のみを消費し、次の単語2[A-Za-z]+
を先読みし、一致したテキストもキャプチャします。(?=(\s[A-Za-z]+))
関数に渡されたreplace
関数は、最初の引数として一致した文字列を受け取り、後続の引数でキャプチャされたテキストを受け取ります。(他にもあります-ドキュメントを確認してください-ここでは必要ありません)。先読みはゼロ幅(入力は消費されない) であるため、一致全体も最初の単語であることが便利です。先読みのキャプチャ テキストは、2 番目の引数に入ります。
RegExp.exec による適切な解決策
String.replace
置換結果はまったく使用されないため、関数には置換オーバーヘッドが発生することに注意してください。これが受け入れられない場合はRegExp.exec
、ループ内の関数を使用して上記のコードを書き直すことができます。
var output = [];
var str = "Mary had a little lamb";
var re = /[A-Za-z]+(?=(\s[A-Za-z]+))/g;
var arr;
while ((arr = re.exec(str)) != null) {
output.push(arr[0] + arr[1]);
}
脚注
可変幅の否定後読みをサポートする正規表現の他のフレーバーでは、前の単語を取得することは可能ですが、JavaScript 正規表現は否定後読みをサポートしていません!
(?=pattern)
先読みの構文です。
付録
String.match
g
フラグを使用するとキャプチャ グループが無視されるため、ここでは使用できません。入力の消費を回避し、重複するテキストと一致させるためにルックアラウンドが必要なため、正規表現ではキャプチャ グループが必要です。