Düzenli İfadelere (Regex) Pratik Giriş
C
Düzenli İfadelere (Regex) Pratik Giriş
Düzenli ifadeler (regular expressions, kısaca regex) ilk bakışta ^(\d{3})-(\d{4})$ gibi anlaşılmaz bir simge yığını gibi görünür. Oysa regex, "bir metnin belirli bir kalıba uyup uymadığını" tarif etmenin sıkıştırılmış bir dilidir. Yapı taşları aslında az sayıdadır; bir kez kavradığınızda e-posta doğrulamadan log ayıklamaya kadar her yerde işinize yarar.
Regex tam olarak neyi çözer?
Şu işleri düşünün: bir formdaki telefon numarasının geçerli olup olmadığını kontrol etmek, koca bir metinden tüm tarihleri çekip almak, bir dosyadaki tüm TODO satırlarını bulmak. Bunların hepsi "kalıp eşleştirme" problemidir ve regex tam da bunun için vardır.
JavaScript'te basit bir örnek:
const metin = "Sipariş no: 312-4455";
const kalip = /(\d{3})-(\d{4})/;
const sonuc = metin.match(kalip);
console.log(sonuc[0]); // "312-4455"
console.log(sonuc[1]); // "312" (ilk grup)
Temel yapı taşları
Düz karakterler kendileriyle eşleşir: kedi kalıbı metindeki "kedi" kelimesini bulur.
Karakter sınıfları bir grup olasılığı temsil eder:
\d→ bir rakam (0-9)\w→ bir harf, rakam veya alt çizgi\s→ bir boşluk karakteri.→ herhangi bir karakter (yeni satır hariç)[a-f]→ a'dan f'ye herhangi bir harf[^0-9]→ rakam olmayan herhangi bir karakter
Niceleyiciler "kaç kez" sorusunu yanıtlar:
*→ sıfır veya daha fazla+→ bir veya daha fazla?→ sıfır veya bir (yani isteğe bağlı){3}→ tam olarak 3 kez{2,5}→ 2 ile 5 kez arası
Çapalar (anchors) konumu belirtir:
^→ satırın başı$→ satırın sonu\b→ kelime sınırı
Aşağıdaki görsel, tek bir kalıbın parçalarının nasıl bir araya geldiğini gösteriyor:

Gruplar ve yakalama
Parantezler ( ) hem bir parçayı gruplar hem de o kısmı "yakalar" (capture), yani sonradan erişebilmeniz için saklar. Üstteki örnekte (\d{3}) ve (\d{4}) iki ayrı grup oluşturur; match sonucunda bunlara sonuc[1] ve sonuc[2] ile ulaşırsınız.
Yakalamaya ihtiyacınız yoksa (?:...) ile "yakalamayan grup" kullanın; bu hem niyetinizi belli eder hem de performansı bir nebze iyileştirir.
İsimli gruplar okunabilirliği artırır:
const kalip = /(?<alan>\d{3})-(?<no>\d{4})/;
const { groups } = "312-4455".match(kalip);
console.log(groups.alan); // "312"
console.log(groups.no); // "4455"
Sık yapılan hatalar
1. Açgözlü (greedy) eşleşme. .* mümkün olan en uzun parçayı yakalar. <b>kalın</b> içinde <.*> kalıbı tüm satırı yutar. Bunun yerine "tembel" sürümü <.*?> kullanın; en kısa eşleşmeyi alır.
2. Özel karakterleri kaçırmamak. ., +, *, ?, (, ) gibi karakterler özel anlam taşır. Gerçek bir nokta aramak istiyorsanız \. yazmalısınız. Örneğin dosya uzantısı için \.jpg$.
3. Her şeyi regex ile çözmeye çalışmak. HTML veya JSON gibi iç içe geçmiş yapıları regex ile ayrıştırmak kırılgandır. Bu işler için uygun bir ayrıştırıcı (parser) kullanın. Regex; satır, kelime ve basit kalıplar için parlar.
Faydalı birkaç hazır kalıp
// Basit e-posta (mükemmel değil ama çoğu durum için yeterli)
/^[\w.+-]+@[\w-]+\.[\w.-]+$/
// Baştaki/sondaki boşlukları bulma
/^\s+|\s+$/g
// Bir metindeki tüm hashtag'ler
/#\w+/g
// Türkçe karakterler dahil bir kelime
/[a-zçğıöşü]+/i
Sonundaki bayraklara dikkat edin: g (global) tüm eşleşmeleri bulur, i (insensitive) büyük/küçük harf ayrımını kaldırır.
Bul ve değiştir: regex'in asıl gücü
Regex yalnızca "var mı yok mu" kontrolü için değildir; asıl gücünü dönüştürme işlerinde gösterir. replace ile yakaladığınız grupları yeni metinde yeniden kullanabilirsiniz:
// "2026-06-12" → "12.06.2026"
const tarih = "2026-06-12";
tarih.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3.$2.$1");
// "12.06.2026"
$1, $2 sırasıyla birinci ve ikinci yakalama grubunu temsil eder. İsimli gruplarla aynı iş daha okunaklı olur:
tarih.replace(/(?<yil>\d{4})-(?<ay>\d{2})-(?<gun>\d{2})/, "$<gun>.$<ay>.$<yil>");
Bu teknik, editörünüzde de çalışır: VS Code'un "Bul ve Değiştir" panelinde regex modunu açarsanız (Alt+R), yüzlerce satırlık mekanik düzenlemeyi tek hamlede yaparsınız. Benim en sık kullandığım örnek, bir listedeki değerleri SQL ya da JSON formatına çevirmek: ^(.+)$ bulup "$1", ile değiştirin, satırlar tırnaklanmış hâlde önünüzde.
İleri ve geri bakış (lookahead / lookbehind)
Bazen bir kalıbın "yanında ne olduğuna" bakmak ama o kısmı eşleşmeye dahil etmemek istersiniz. Bunu bakış grupları yapar:
(?=...)→ ilerisi şuna uyuyorsa (pozitif lookahead)(?!...)→ ilerisi şuna uymuyorsa (negatif lookahead)(?<=...)→ gerisi şuna uyuyorsa (pozitif lookbehind)
Klasik kullanım, şifre kurallarıdır — "en az bir rakam VE en az bir büyük harf içersin":
/^(?=.*\d)(?=.*[A-Z]).{8,}$/
Buradaki iki lookahead, konum ilerletmeden iki ayrı koşulu kontrol eder; .{8,} ise asıl eşleşmeyi yapar. Bir diğer pratik örnek: fiyatlardaki sayıyı para birimine dokunmadan yakalamak — (?<=₺)\d+ kalıbı "₺250" içindeki yalnızca 250'yi eşler.
Gerçek bir örnek: log dosyasından veri ayıklamak
Kendi sunucumun erişim loglarından hata satırlarını incelerken şu tarz bir kalıp kullanıyorum:
const satir = '2026-06-11 22:14:05 [ERROR] /api/shares 500 (12ms)';
const kalip = /^(\S+ \S+) \[(\w+)\] (\S+) (\d{3})/;
const [, zaman, seviye, yol, durum] = satir.match(kalip);
// zaman: "2026-06-11 22:14:05", seviye: "ERROR", yol: "/api/shares", durum: "500"
Kalıbı parça parça okuyun: ^(\S+ \S+) baştaki tarih-saat ikilisini, \[(\w+)\] köşeli parantezdeki seviyeyi, (\S+) URL'yi, (\d{3}) üç haneli durum kodunu yakalar. Binlerce satırlık log, birkaç dakikada filtrelenebilir bir tabloya dönüşür.
Performans tuzağı: felaket geri dönüşü
İç içe niceleyiciler bazı girdilerde regex motorunu üstel bir döngüye sokabilir; buna catastrophic backtracking denir. Örneğin (a+)+$ kalıbı, sonu eşleşmeyen uzun bir "aaaa..." girdisinde milyonlarca kombinasyon dener ve uygulamanızı dondurabilir. Kullanıcıdan gelen veriyi doğrulayan kalıplarda bu, hizmet dışı bırakma (ReDoS) açığına dönüşür.
Korunmak basit: iç içe niceleyicilerden kaçının, kalıbı mümkün olduğunca belirgin yazın (.* yerine [^"]* gibi) ve şüpheli kalıpları regex101'in "debugger" sekmesinde adım sayısıyla test edin.
Nasıl pratik yapmalı?
Regex öğrenmenin en hızlı yolu denemektir. regex101.com gibi araçlar, yazdığınız kalıbı anlık olarak test eder ve her parçanın ne işe yaradığını açıklar. Önce küçük kalıplarla başlayın, sonra parçaları birleştirin.
Sonuç
Regex, az sayıda yapı taşının birleşmesinden oluşan güçlü bir mini dildir: karakter sınıfları "ne", niceleyiciler "kaç kez", çapalar "nerede" sorusunu yanıtlar. Açgözlü eşleşme ve kaçış karakterleri gibi birkaç tuzağı bilirseniz, günlük metin işleme işlerinin büyük kısmını tek satırla halledebilirsiniz. Korkutucu görünen o simge dizisi, aslında düşündüğünüzden çok daha okunabilir.
Ek Görseller
Diğer Paylaşımlar
Git ile Verimli Sürüm Kontrolü: Günlük İş Akışı Rehberi
Git ile Verimli Sürüm Kontrolü: Günlük İş Akışı Rehberi Çoğu geliştirici Git'i günde onlarca kez kullanır ama çoğu zaman yalnızca üç komutla
30 Mayıs 2026 Web GeliştirmeSocket.IO ile Oda Tabanlı Gerçek Zamanlı Oyun Geliştirmek: Kelime Sayar'dan Dersler
Socket.IO ile Oda Tabanlı Gerçek Zamanlı Oyun Geliştirmek: Kelime Sayar'dan Dersler Kelime Sayar, arkadaş gruplarının oda kurup birlikte oyn
14 Temmuz 2026 Sunucu YönetimiNode.js Sitenizi Cloudflare Arkasında Yayınlamak: Sertifikalar, Gerçek IP ve Önbellek
Node.js Sitenizi Cloudflare Arkasında Yayınlamak: Sertifikalar, Gerçek IP ve Önbellek Bu site, ilk günden beri Cloudflare arkasında çalışıyo
16 Haziran 2026 GüvenlikExpress.js Uygulamanızı Güvene Almak: Oturumlar, CSRF ve Hız Sınırlama
Express.js Uygulamanızı Güvene Almak: Oturumlar, CSRF ve Hız Sınırlama Express ile bir uygulamayı ayağa kaldırmak yarım saat sürer; onu inte
14 Haziran 2026