Regex (Düzenli İfadeler) Nedir?
Bir metin içinde belirli bir kalıba uyan parçaları bulmak, doğrulamak ya da değiştirmek istediğinizde hep aynı sorunla karşılaşırsınız: indexOf veya includes gibi sabit metin arayan fonksiyonlar, değişken uzunlukta veya farklı biçimlerde tekrar eden kalıpları ifade edemez. Bir e-posta adresinin, telefon numarasının ya da IP adresinin geçerli formatta olup olmadığını kontrol etmek için sabit bir metin değil, bir kural tanımlamanız gerekir. Regex (regular expression, düzenli ifade) tam olarak bunu yapar: karakter dizilerini tanımlamak için kullanılan, kendi başına küçük bir söz dizimi olan bir mini dildir.
Regex, neredeyse her programlama dilinde (JavaScript, PHP, Python, Java) ve birçok araçta (metin editörleri, komut satırı araçları, veritabanı sorguları) aynı temel mantıkla çalışır. Söz dizimi dilden dile küçük farklar gösterse de karakter sınıfları, kantalayıcılar ve gruplar gibi temel kavramlar ortaktır. Bu rehberde JavaScript'in yerleşik RegExp motorunu esas alıyoruz; bu motor tarayıcıda ve Node.js'te aynı şekilde çalışır.
Regex'in Temel Yapı Taşları
Bir regex deseni birkaç temel yapı taşından oluşur. Bunları tek tek anlamak, ilk bakışta karmaşık görünen bir deseni okunabilir hale getirir.
| Yapı | Ne İşe Yarar | Örnek |
|---|---|---|
| Karakter sınıfları | Belirli bir karakter kümesiyle eşleşir: \d rakam, \w harf/rakam/alt çizgi, \s boşluk karakteri. Büyük harfli hâlleri (\D, \W, \S) tam tersini, yani o kümede olmayan karakterleri eşler. | \d{3} tam olarak 3 rakam |
| Özel karakter sınıfları | Köşeli parantez içinde kendi kümenizi tanımlarsınız; başta ^ varsa küme dışındaki her şeyi eşler. | [aeiou] sesli harfler, [^0-9] rakam olmayanlar |
| Kantalayıcılar (quantifiers) | Önündeki öğenin kaç kez tekrar edeceğini belirtir: * sıfır veya daha fazla, + bir veya daha fazla, ? sıfır veya bir, {n,m} n ile m arası. | \d{2,4} 2 ila 4 rakam |
| Çıpalar (anchors) | Bir konuma işaret eder, karakter tüketmez: ^ metnin başı, $ metnin sonu, \b kelime sınırı. | ^\d+$ baştan sona sadece rakam |
| Gruplar | Parantez birden çok karakteri tek birim gibi ele almanızı ve kantalayıcı uygulamanızı sağlar; (?:...) yakalamayan (non-capturing) gruptur. | (ab)+ ab, abab, ababab... |
| Alternation | Dikey çizgi ile birden fazla seçenekten birini eşler. | kedi|köpek |
Bayraklar (Flags): g, i, m, s
Bir regex deseninin sonuna eklenen bayraklar motorun davranışını değiştirir. g (global) bayrağı, metindeki yalnızca ilk eşleşmeyi değil tüm eşleşmeleri bulur; bu bayrak olmadan JavaScript'te .exec() her zaman sadece ilk sonucu döndürür. i (case-insensitive) büyük/küçük harf farkını yok sayar. m (multiline) açıkken ^ ve $ çıpaları tüm metnin başı/sonu yerine metindeki her satırın başı ve sonuyla eşleşir. s (dotAll) açıkken normalde satır sonu karakterini (\n) eşlemeyen . joker karakteri, satır sonlarını da kapsar.
JavaScript'in yerleşik RegExp motoru (ECMAScript standardı), PHP veya Perl'de kullanılan PCRE ya da Python'un re modülü gibi bazı ileri özellikleri desteklemez; örneğin özyinelemeli (recursive) desenler ya da koşullu (conditional) ifadeler yoktur. Modern tarayıcılarda geriye bakma (lookbehind, (?<=...) ve (?<!...)) artık desteklenir, ancak aynı deseni farklı bir dilde veya eski bir ortamda da çalıştıracaksanız bu taşınabilirlik farkını akılda tutmakta fayda var.
Gerçek Örnekler Üzerinden Regex
Aşağıdaki üç örnek, günlük geliştirme işlerinde sık karşılaşılan senaryoları gösteriyor.
- Basit e-posta benzeri desen:
\b\w+@\w+\.\w+\bdeseni, kullanıcı adı, @ işareti ve bir nokta içeren alan adından oluşan metinleri yakalar. Bunun gerçek RFC 5322 e-posta doğrulaması olmadığını, yalnızca pratik bir yaklaşım olduğunu unutmayın — gerçek bir e-posta adresinin varlığını doğrulamak için sunucu tarafında ayrıca bir onay adımı (doğrulama e-postası) kullanılmalıdır. - Sadece rakamları çekmek:
/\d+/gdeseni bir metindeki tüm rakam gruplarını bulur; örneğin bir telefon numarası alanından ayraç, boşluk ve parantezleri atıp yalnızca rakamları almak içintext.replace(/\D/g, '')kullanılabilir (\D, rakam olmayan her karakterle eşleşir). - Baştaki/sondaki boşlukları temizlemek:
/^\s+|\s+$/gdeseni, metnin başındaki ya da sonundaki boşluk karakterlerini (boşluk, tab, satır sonu) yakalar; bunu boş dizeyle değiştirmek,String.prototype.trim()metodunun elle regex ile yeniden üretilmiş hâlidir.
Yeni Başlayanların Sık Yaptığı Hatalar
- Greedy ile lazy kantalayıcıyı karıştırmak:
*,+ve{n,m}varsayılan olarak greedy'dir, yani eşleşen en uzun diziyi almaya çalışır. HTML benzeri bir metinde<.+>deseni ilk<ile son>arasındaki her şeyi tek eşleşme olarak yutabilir. Sona bir?ekleyerek (<.+?>) kantalayıcıyı lazy yapmak, mümkün olan en kısa eşleşmeyi bulmasını sağlar. - Özel karakterleri kaçırmayı (escape) unutmak:
. * + ? ( ) [ ] { } ^ $ |gibi karakterlerin regex'te özel bir anlamı vardır. Bir fiyatta geçen noktayı (19.99) ararken19.99yazarsanız nokta "herhangi bir karakter" anlamına gelir; gerçek bir nokta aramak için19\.99yazıp ters eğik çizgiyle (backslash) özel anlamını iptal etmeniz gerekir. - Zararlı geri izleme (catastrophic backtracking): İç içe geçmiş kantalayıcılar (örneğin
(a+)+bgibi bir desen) eşleşmeyen girdilerde motorun binlerce olası kombinasyonu denemesine ve işlem süresinin katlanarak artmasına yol açabilir. Bu, bir web sayfasını veya sunucu tarafı bir servisi geçici olarak kilitleyebilecek gerçek bir performans riskidir (ReDoS); bu yüzden özellikle dışarıdan gelen girdiyle çalışan desenleri dikkatli tasarlamak gerekir. - Çıpa kullanmayı unutmak: Bir değerin baştan sona tamamen belirli bir formatta olduğunu doğrulamak istediğinizde
^ve$çıpalarını eklemezseniz, desen metnin herhangi bir yerinde kısmi bir eşleşme bulduğunda da "geçerli" sonucunu verir. Örneğin^\d{5}$yalnızca tam olarak 5 rakamdan oluşan bir dizeyi kabul ederken, çıpasız\d{5}"abc12345xyz" gibi bir dizenin içinde de eşleşme bulur.
Deseninizi Güvenle Test Edin
Bir regex deseni yazarken önce küçük ve gerçekçi test verileriyle deneme yapmak, üretime çıkmadan önce kaç eşleşme bulunduğunu, yakalama gruplarının ne döndürdüğünü ve deseninizin beklenmedik girdilerde nasıl davrandığını görmenizi sağlar. KEYDAL'ın regex test aracı, yazdığınız deseni gerçek zamanlı olarak örnek bir metne uygular, eşleşmeleri vurgular ve yakalama gruplarını ayrı ayrı listeler — hepsi tarayıcınızda çalışır, hiçbir veri sunucuya gönderilmez.
Deseninizi canlı olarak test edin, eşleşmeleri ve yakalama gruplarını anında görün.