Yalnızca yakalanan gruplar nasıl değiştirilir?


196

Ben önce ve sonra dize HTML kodu var:

name="some_text_0_some_text"

Ben gibi bir 0şey ile değiştirmek istiyorum:!NEW_ID!

Bu yüzden basit bir normal ifade yaptım:

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

Ama sadece ele geçirilen bloğun nasıl değiştirileceğini göremiyorum.

($ 1) gibi yakalanan bir sonucu başka bir dizeyle değiştirmenin bir yolu var mı?

Sonuç:

name="some_text_!NEW_ID!_some_text"

Yanıtlar:


359

Bir çözüm, önceki ve sonraki metin için yakalama eklemektir:

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

76
Gelecekten selamlar! Çözümünüz gerçekten düzgün görünüyor. Cevabınızı açıklar mısınız?
Mart'ta Polyducks

21
Parantez "gruplar" oluşturmak için kullanılır, daha sonra a ile değiştirerek erişilebilen bir temel-1 dizini atanır $, bu nedenle ilk kelime (\w+)bir gruptadır $1ve orta kısım (\d+)ikinci gruptur (ancak yerine yok sayılır) ve üçüncü grup $3. Dolayısıyla, değiştirme dizesini verdiğinizde, "$1!new_ID!$3"$ 1 ve $ 3 otomatik olarak birinci grup ve üçüncü grupla değiştirilir ve 2. grubun yeni dize ile değiştirilmesini sağlar ve onu çevreleyen metni korur.
mix3d

4
Bununla birlikte, NASIL çalıştığını anlarken, daha zarif bir çözüm umuyordum>. <Yine de, şimdi kodumla ilerleyebilirim!
16:16

9
1) Yakalamanıza bile gerek yok \ d + 2) Neden zarif olmadığını söylüyorsunuz? Yakalamak bir şeyi saklamak, atmak değil. Tutmak istediğiniz şey AROUND \ d + 'dır, bu yüzden bu çevreleyen parçaları yakalamak gerçekten mantıklıdır (ve yeterince zariftir).
Sir4ur0n

3
Güzel çözüm. Dönüşüm için temel olarak yakalama grubunu kullanarak yakalama gruplarını değiştirmek istersek ne olur? Bunu yapmak için aynı derecede zarif bir çözüm var mı? Şu anda yakalanan grupları bir listede saklıyorum, bunları döngüye alıyorum ve her yinelemede yakalama grubunu dönüştürülen değerle değiştiriyorum
sookie

15

Artık Javascript'in ( ES2018'den itibaren ) geriye baktığına göre , daha yeni ortamlarda, bu gibi durumlarda gruplardan tamamen kaçınabilirsiniz. Aksine örnek olarak geriye dönük sen yakalama edildi grubun önce gelir ve lookahead için sonra gelir ve ile değiştirin ne için sadece !NEW_ID! :

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

Bu yöntemle, tam eşleme yalnızca değiştirilmesi gereken bölümdür.

  • (?<=name="\w+)- Sonradan name"kelime karakterleri (Neyse ki, geriye bakışların Javascript'te sabit genişliğe sahip olması gerekmez!)
  • \d+ - Bir veya daha fazla basamağı eşleştirin - desenin bir arama alanında olmayan tek kısmı, dizenin elde edilen eşleşmede bulunacak tek kısmı
  • (?=\w+")- Kelime karakterleri ve ardından " `

Gözünüzün oldukça yeni olduğunu unutmayın. V8'in modern sürümlerinde (Chrome, Opera ve Node dahil) çalışır, ancak en azından henüz diğer ortamlarda çalışmaz. Bu nedenle, Nob'da ve kendi tarayıcınızda (V8'in modern bir sürümünde çalışıyorsa) lookbehind'i güvenilir bir şekilde kullanabilmenize rağmen, henüz rastgele istemciler (genel bir web sitesinde olduğu gibi) tarafından yeterince desteklenmemektedir.


Sadece hızlı bir zamanlama testi yaptık
Kaiido

Ama, örneğin, birden fazla sayı çıkarmak ve "geri koymak", ben de gruplamak zorunda kalacak \d+, değil mi?
Mosh Feu

@MoshFeu Bir replacer işlevi kullanın ve tüm eşleşmeyi kullanın, rakamlar: ikinci parametreyi değiştirin match => match * 2. Rakamlar hala tüm maç, bu yüzden gruplara gerek yok
CertainPerformance

Yakaladım seni. Teşekkürler!
Mosh Feu

2

Matthew'in cevabındaki küçük bir gelişme, son yakalama grubu yerine bir ileriye doğru olabilir:

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

Veya ondalık sayıya bölünebilir ve yeni kimliğinizle şu şekilde katılabilirsiniz:

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

Örnek / Burada karşılaştırma: https://codepen.io/jogai/full/oyNXBX


1

İki ele geçirme grubu ile de mümkün olurdu; Ayrıca, basamaklardan önce ve sonra ek sol ve sağ sınırlar olarak iki tire eklerdim ve değiştirilen ifade şöyle görünürdü:

(.*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);


İfadeyi keşfetmek / basitleştirmek / değiştirmek istiyorsanız, ifadenin sağ üst panelinde açıklanmıştır. regex101.com'un açıklanmıştır . İsterseniz, bu bağlantıda bazı örnek girdilerle nasıl eşleşeceğini de izleyebilirsiniz .


RegEx Devresi

jex.im düzenli ifadeleri görselleştirir:

resim açıklamasını buraya girin


0

Daha basit bir seçenek, sadece rakamları yakalamak ve değiştirmek.

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);

kaynaklar

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.