キャプチャしたグループのみを置き換える方法は?


193

文字列の前後にHTMLコードがあります。

name="some_text_0_some_text"

私はのようなものに置き換え0たいです:!NEW_ID!

だから私は簡単な正規表現を作りました:

.*name="\w+(\d+)\w+".*

しかし、キャプチャされたブロックのみを置き換える方法はわかりません。

($ 1)のようなキャプチャされた結果を他の文字列で置き換える方法はありますか?

結果は次のようになります:

name="some_text_!NEW_ID!_some_text"

回答:


358

解決策は、前後のテキストのキャプチャを追加することです。

str.replace(/(.*name="\w+)(\d+)(\w+".*)/, "$1!NEW_ID!$3")

76
未来からのご挨拶!あなたのソリューションは本当にきれいに見えます。あなたの答えを説明していただけませんか?
Polyducks

21
括弧は「グ​​ループ」を作成するために使用されます。これは、基数1のインデックスを割り当てられ、で置換してアクセスできる$ため、最初の単語(\w+)はグループになり$1、中央の部分(\d+)は2番目のグループになります(ただし、置換では無視されます)、3番目のグループは$3です。したがって、の置換文字列を指定する"$1!new_ID!$3"と、$ 1と$ 3は自動的に最初のグループと3番目のグループに置き換えられ、2番目のグループを新しい文字列に置き換えて、周囲のテキストを維持します。
mix3d 2016年

4
そうは言っても、どのように機能するかは理解していますが、より洗練されたソリューションを望んでいました。>それでも、コードを先に進めることができます!
mix3d 2016年

9
1)\ d +をキャプチャする必要すらありません2)なぜエレガントではないと言うのですか?キャプチャは、物を捨てずに保管することを目的としています。残しておきたいのは、\ d +の周りのものなので、これらの周囲のパーツをキャプチャすることは本当に理にかなっています(そして十分にエレガントです)。
Sir4ur0n

3
素晴らしい解決策。変換のベースとしてキャプチャグループを使用してキャプチャグループを置き換える場合はどうなりますか?これを行うための同様にエレガントな解決策はありますか?現在、キャプチャされたグループをリストに格納し、ループして、キャプチャグループを各反復で変換された値に置き換えています
sookie

15

Javascriptが(ES2018の時点で)後読みを持つようになったため、新しい環境では、このような状況ではグループを完全に回避できます。むしろ、キャプチャしているグループの前に来るものを後読みし、先読みを後にし、単に !NEW_ID!次のものに置き換えます

const str = 'name="some_text_0_some_text"';
console.log(
  str.replace(/(?<=name="\w+)\d+(?=\w+")/, '!NEW_ID!')
);

この方法では、完全一致は交換が必要な部分のみです。

  • (?<=name="\w+)-の後読みname"、その後に単語文字(幸いなことに、後読みはJavascriptで固定幅である必要はありません!)
  • \d+ -1つ以上の数字に一致-ルックアラウンドにないパターンの一部のみ、結果の一致に含まれる文字列の一部のみ
  • (?=\w+")-単語文字の先に" `を付けて

後読みはかなり新しいことを覚えておいてください。最新バージョンのV8(Chrome、Opera、Nodeを含む)で動作しますが、少なくとも他のほとんどの環境では動作しません。したがって、Nodeと独自のブラウザー(最新バージョンのV8で実行されている場合)で後読みを確実に使用できますが、ランダムクライアント(パブリックWebサイトなど)ではまだ十分にサポートされていません。


ただ、迅速なタイミングテストを実行し、それがどのように入力された事項は非常に印象的です:jsfiddle.net/60neyop5
Kaiido

しかし、たとえば、複数の数値を抽出して「戻す」場合は、グループ化する必要がありますよ\d+ね?
Mosh Feu

@MoshFeu置換関数を使用して、完全一致の数字を使用しmatch => match * 2ます。2番目のパラメーターをに置き換えます。数字はまだ全体の試合なので、グループのための必要はありません
CertainPerformance

つかまえた。ありがとう!
Mosh Feu

2

マシューの答えを少し改善するには、最後のキャプチャグループの代わりに先読みをすることができます。

.replace(/(\w+)(\d+)(?=\w+)/, "$1!NEW_ID!");

または、10進数で分割して、次のように新しいIDで結合することもできます。

.split(/\d+/).join("!NEW_ID!");

例/ここのベンチマーク:https : //codepen.io/jogai/full/oyNXBX


1

2つのキャプチャグループを使用することも可能でした。数字の前後に追加の左と右の境界として2つのダッシュを含めることもでき、変更後の式は次のようになります。

(.*name=".+_)\d+(_[^"]+".*)

const regex = /(.*name=".+_)\d+(_[^"]+".*)/g;
const str = `some_data_before name="some_text_0_some_text" and then some_data after`;
const subst = `$1!NEW_ID!$2`;
const result = str.replace(regex, subst);
console.log(result);


式を探索/簡略化/変更したい場合は、regex101.comの右上のパネルで説明されてい ます。必要に応じて、このリンクで、サンプル入力とどのように一致するかを確認することもできます。


RegEx回路

jex.imは正規表現を視覚化します。

ここに画像の説明を入力してください


0

単純なオプションは、数字をキャプチャして置き換えるだけです。

const name = 'preceding_text_0_following_text';
const matcher = /(\d+)/;

// Replace with whatever you would like
const newName = name.replace(matcher, 'NEW_STUFF');
console.log("Full replace", newName);

// Perform work on the match and replace using a function
// In this case increment it using an arrow function
const incrementedName = name.replace(matcher, (match) => ++match);
console.log("Increment", incrementedName);

資源

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.