Menu

JavaScript Regex: test, match, replace ve Gruplar

JavaScript'te düzenli ifadeler nasıl çalışır? Pattern oluşturma, temel metotlar (test, match, replace), flag'ler ve yakalama grupları gerçek örneklerle.

Regex Nedir? Metin Eşleştirmek İçin Desenler

JavaScript düzenli ifadeler (regex), string'lerin biçimini tarif etmenin bir yolu: "dört basamaklı sayı", "virgülle biten bir kelime" ya da "e-postaya benzeyen herhangi bir şey" gibi. JavaScript'te bir regex oluşturmanın iki yolu var:

index.js
Output
Click Run to see the output here.

Çoğunlukla kullanacağın yazım şekli birebir bu: deseni iki eğik çizgi arasına alıyorsun, flag'leri de kapanış eğik çizgisinden sonra yazıyorsun. Ama desenin kendisi dinamikse, yani kullanıcı girdisinden ya da bir değişkenden oluşturuyorsan, new RegExp(...) devreye girer.

Sondaki i bir flag. i büyük-küçük harf duyarsız eşleşme anlamına geliyor. Flag'lere birazdan ayrıntılı gireceğiz.

test: Eşleşme Var mı?

Bir regex'e sorabileceğin en basit soru şu: "bu string'in içinde bir eşleşme var mı?" İşte tam bu noktada test devreye giriyor:

index.js
Output
Click Run to see the output here.

\d "herhangi bir rakam" anlamına gelir. test sadece true ya da false döner, başka bir şey değil. Elinizde sadece evet/hayır cevabı yeterliyse — bir alanı doğrulamak, bir diziyi filtrelemek gibi — test tam aradığınız araçtır.

match: Eşleşen Metni Yakalamak

Eşleşen metnin kendisine ihtiyacınız olduğunda, string'in match metodunu kullanın:

index.js
Output
Click Run to see the output here.

g flag'i olmadan match, ilk eşleşmeyi index ve input gibi meta bilgilerle birlikte bir dizi olarak döner. g flag'i ile birlikte kullandığında ise tüm eşleşmeleri düz bir string dizisi şeklinde verir. Hiçbir eşleşme yoksa boş dizi değil, null döndüğünü unutma; ona göre kontrol etmen gerekir:

index.js
Output
Click Run to see the output here.

Flag'ler Kalıbın Davranışını Değiştirir

Flag'ler kapanış slash'ının arkasına gelir ve eşleşmenin nasıl yapılacağını belirler. En sık kullanacakların şunlar:

  • g — global; sadece ilk eşleşmeyi değil, tüm eşleşmeleri bulur.
  • i — büyük/küçük harf duyarsız eşleşme.
  • m — çok satırlı mod; ^ ve $ artık yalnızca string'in başı/sonu değil, her satırın başı/sonu ile eşleşir.
  • s — dotall; . karakteri yeni satır karakterleriyle de eşleşir.
  • u — unicode uyumlu; birçok emoji ve ASCII dışı kalıp için gerekli.
index.js
Output
Click Run to see the output here.

m olmadan ^ yalnızca stringin en başına sabitlenir. m ile birlikte ise her satırın başına sabitlendiği için hem Roses hem de Violets yakalanır.

Karakter Sınıfları ve Niceleyiciler

Çoğu desenin yapı taşları şunlar:

  • \d rakam, \w kelime karakteri (harf/rakam/alt çizgi), \s boşluk.
  • [abc] a, b veya c'den biri. [^abc] bunların dışındaki her şey. [a-z] bir aralık.
  • . yeni satır dışındaki herhangi bir karakter.
  • * sıfır veya daha fazla, + bir veya daha fazla, ? sıfır ya da bir.
  • {3} tam olarak üç, {2,5} iki ile beş arası, {2,} iki ya da daha fazla.
  • ^ başlangıç, $ bitiş.

Hepsini bir araya getirelim:

index.js
Output
Click Run to see the output here.

\b bir kelime sınırıdır — yani bir kelime karakteri ile kelime olmayan bir karakter arasındaki görünmez çizgi. "Tam kelime" eşleşmesi yapmak istediğinizde işinize yarar.

Yakalama Grupları: Eşleşmenin Parçalarını Hatırlamak

Parantezler, eşleşen kısmı yakalayan bir grup oluşturur. exec ve match, genel eşleşmenin yanında bu yakalamaları da döndürür:

index.js
Output
Click Run to see the output here.

0 numaralı indekste tüm eşleşmenin kendisi bulunur, ardından her grup kendi yerini alır. Ama ikiden fazla grubun olduğu durumlarda sıra sayarak gitmek can sıkıcı oluyor; o yüzden gruplara isim verelim:

index.js
Output
Click Run to see the output here.

İsimlendirilmiş gruplar, kullanım yerinde çok daha okunaklı duruyor; üstelik pattern içindeki sırayı değiştirdiğinizde de bozulmuyor.

replace: Eşleşen Metni Yeniden Yazma

replace metodu bir pattern ve bir de yerine yazılacak değer alır. Bu değer bir string olabileceği gibi bir fonksiyon da olabilir:

index.js
Output
Click Run to see the output here.

g bayrağını koymadığınızda yalnızca ilk eşleşme değiştirilir. Sık yapılan hatalardan biri bu bayrağı unutup ikinci e-postanın neden hâlâ bozuk göründüğüne şaşırmaktır.

Değiştirme (replacement) metinleri geri referans (back-reference) desteği sunar. $1, $2 gibi ifadeler yakalama gruplarına, $<isim> ise isimlendirilmiş gruplara karşılık gelir:

index.js
Output
Click Run to see the output here.

Basit bir değiştirme dışında daha karmaşık bir işlem yapacaksanız, ikinci parametre olarak bir fonksiyon verebilirsiniz. Bu fonksiyon; eşleşen metni ve yakalama gruplarını argüman olarak alır:

index.js
Output
Click Run to see the output here.

Alt çizgi eşleşmenin tamamını temsil ediyor (bize lazım değil); n ise ilk yakalama grubu. Regex artı replacer fonksiyonu kombinasyonu, gerçek hayatta karşılaştığınız metin düzenleme işlerinin büyük çoğunluğunu rahatlıkla halleder.

matchAll: Tüm eşleşmeleri yakalama gruplarıyla birlikte

String.prototype.matchAll, her eşleşmeyi yakalama gruplarıyla birlikte dönen bir iterator verir — ki bunu g bayrağıyla kullandığınız sade match ile yapamazsınız:

index.js
Output
Click Run to see the output here.

matchAll kullanırken g flag'i zorunlu. Onsuz TypeError alırsın. Iterator yerine rastgele erişim lazımsa diziye yay: [...text.matchAll(email)].

Özel Karakterleri Kaçışlama (Escape)

Regex'te . * + ? ( ) [ ] { } | \ ^ $ gibi karakterlerin özel bir anlamı vardır. Bunları birebir karakter olarak eşleştirmek istiyorsan başına ters eğik çizgi koyup kaçışlaman gerekir:

index.js
Output
Click Run to see the output here.

Kaçış uygulanmamış hali examplexcom ile de eşleşir; çünkü . "herhangi bir karakter" anlamına gelir. Bu tür hatalar hem yaygın hem de sessiz sedasızdır — regex'iniz olması gerekenden fazlasını yakalıyorsa ilk iş olarak kaçışsız bir . var mı diye bakın.

Kullanıcı girdisinden bir pattern oluştururken bu girdiyi mutlaka escape etmelisiniz; aksi hâlde kullanıcı regex sözdizimi enjekte edebilir:

index.js
Output
Click Run to see the output here.

$& bir replacement string içinde "eşleşen metnin tamamı" anlamına gelen bir kısayoldur.

Lookahead ve Lookbehind

Bazen bir metnin yalnızca belirli bir şeyin ardından geldiğinde (ya da öncesinde geldiğinde) eşleşmesini istersin — ama o "şey"in eşleşmenin içine dahil olmasını istemezsin. İşte lookaround dediğimiz yapılar tam olarak bunu yapar:

index.js
Output
Click Run to see the output here.
  • (?= ...) pozitif lookahead: "şunun tarafından takip edilen."
  • (?<= ...) pozitif lookbehind: "şunun tarafından öncelenen."
  • (?! ...) ve (?<! ...) ise bunların negatif karşılıkları.

Lookaround'lar karakter tüketmez, yani "baktığınız" kısım deseninizin bir sonraki parçası için hâlâ kullanılabilir durumda kalır.

E-posta Doğrulama Hakkında Küçük Bir Not

Bu konu sık sık karşınıza çıkacak: "bana e-posta doğrulayan bir regex ver." Dürüst cevap şu: verme. Gerçek e-posta grameri oldukça çetrefilli ve okunabilecek kadar kısa bir regex bir yönden mutlaka hatalıdır. Form doğrulaması için pragmatik bir desen iş görür:

index.js
Output
Click Run to see the output here.

Şöyle okuyun: "boşluk olmayan ve @ içermeyen birkaç karakter, bir @, aynısından biraz daha, bir nokta, yine aynısından biraz daha." Bu kalıp, RFC 5322'yi tam uyguluyormuş gibi davranmadan bariz yazım hatalarını yakalar. Gerçek doğrulama için yine de onay e-postası göndermelisiniz.

Sık Yapılan Hatalar

Akılda tutmaya değer birkaç tuzak:

  • replace veya matchAll ile g flag'ini unutmak. Sadece ilk eşleşmeyi alırsınız ya da TypeError fırlar.
  • Global regex'lerde durumlu lastIndex. g veya y flag'li bir regex, test/exec çağrıları arasında nerede kaldığını hatırlar. Alakasız string'lerde aynı regex'i tekrar kullanmayın — ya her seferinde yenisini oluşturun ya da matchAll'a geçin.
  • Dinamik kalıplarda escape edilmemiş nokta ve slash'lar. Kullanıcı girdisini new RegExp(...) içine atmadan önce mutlaka escape edin.
  • Catastrophic backtracking (yıkıcı geri izleme). (a+)+ gibi iç içe quantifier'lar, kötü niyetli bir girdide sekmeyi kilitleyebilir. Bir regex yavaş hissettiriyorsa, sadeleştirin.

Sırada: Tarih ve Saat

Regex metnin şekliyle ilgilenir; gerçek veride ise ayrıştırılması, formatlanması ve üzerinde işlem yapılması gereken zaman damgaları da vardır. Bir sonraki sayfada Date, Intl.DateTimeFormat ve timezone hatalarından sizi uzak tutacak zihinsel modeli ele alacağız.

Sıkça Sorulan Sorular

JavaScript'te regex nasıl oluşturulur?

İki yolu var. Literal form slash'lar arasında yazılır: /hello/i. Constructor ise string alır: new RegExp('hello', 'i'). Pattern sabitse literal formu tercih edin; pattern'i runtime'da bir değişkenden oluşturacaksanız constructor işinizi görür.

JavaScript regex'te test, match ve exec arasındaki fark nedir?

regex.test(str) boolean döner — sadece eşleşme var mı diye bakıyorsanız en hızlısı budur. str.match(regex) eşleşmeleri dizi olarak verir (yoksa null). regex.exec(str) ise tek seferde bir eşleşme döner; yakalama gruplarını da getirir ve g flag'i ile birlikte lastIndex üzerinden pozisyonu çağrılar arasında takip eder.

JavaScript'te regex ile tüm eşleşmeleri nasıl değiştiririm?

g flag'ini kullanın: str.replace(/foo/g, 'bar'). g olmadan sadece ilk eşleşme değişir. Alternatif olarak str.replaceAll(/foo/g, 'bar') de çağırabilirsiniz — ama dikkat: replaceAll'a regex verdiğinizde g flag'i zorunludur, yoksa hata fırlatır.

JavaScript regex'te yakalama grupları (capture groups) nedir?

Pattern içindeki parantezler, eşleşen kısmı hatırlayan yakalama grupları oluşturur. Örneğin /(\d{4})-(\d{2})/.exec('2024-11') çağrısı bir dizi döner; index 1'de '2024', index 2'de '11' olur. Gruplara isim de verebilirsiniz: (?<year>\d{4}) yazıp sonra match.groups.year ile erişebilirsiniz.

Coddy ile kodlamayı öğren

BAŞLA