Eğitim Portalı/Java/Düzenli İfadeler (Regular Expressions / Regex)
Java01-java/67-regex

Düzenli İfadeler (Regular Expressions / Regex)

Regex, metin içinde desen aramak, doğrulamak ve değiştirmek için kullanılan güçlü bir mini dildir. "Bu metin geçerli bir e-posta mı?", "şu logdaki tüm tarihleri bul", "kart numarasını maskele" gibi işleri tek satırda…

Düzenli İfadeler (Regular Expressions / Regex)

Regex, metin içinde desen aramak, doğrulamak ve değiştirmek için kullanılan güçlü bir mini dildir. "Bu metin geçerli bir e-posta mı?", "şu logdaki tüm tarihleri bul", "kart numarasını maskele" gibi işleri tek satırda yapar. Java'da java.util.regex paketi (Pattern ve Matcher) ile kullanılır; ayrıca String.matches/replaceAll/split kısayolları vardır.

Pattern ve Matcher

İki temel sınıf:

  • Pattern: Derlenmiş bir regex kalıbı (Pattern.compile("\\d+")).
  • Matcher: Kalıbı belirli bir metne uygulayan motor (pattern.matcher(metin)).
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("oda 12, kat 3");
while (m.find()) System.out.println(m.group());  // 12, 3

İki temel arama yöntemi:

  • matches(): Tüm metin kalıba uyuyor mu? (doğrulama için)
  • find(): Metnin içinde kalıbı arar (tüm eşleşmeleri gezer).

Sık kullanılan metakarakterler

SembolAnlamıSembolAnlamı
\drakam+bir veya çok
\wharf/rakam/_*sıfır veya çok
\sboşluk?sıfır veya bir
.herhangi karakter{n,m}n–m tekrar
^ $başlangıç/bitiş[...]karakter kümesi
(...)yakalama grubu``

Java tuzağı: Regex'teki \ Java string'inde \\ yazılır: "\\d+" (regex \d+).

Gruplar

Parantezler alt-parçaları yakalar; group(n) ile erişilir. İsimli gruplar okunabilirliği artırır:

Pattern.compile("(\\d{2})\\.(\\d{2})\\.(\\d{4})");   // group(1)=gün, group(2)=ay...
Pattern.compile("(?<kullanici>\\w+)@(?<alan>[\\w.]+)"); // group("kullanici")

Örnek 1 (./Ornek1.java) matches/find, numaralı ve isimli grupları gösterir.

Doğrulama, değiştirme, bölme

  • Doğrulama: pattern.matcher(metin).matches() (e-posta, telefon formatı).
  • replaceAll(kalip, yenisi): Geri referanslarla ($1, $2) değiştirme — maskeleme, biçimleme, boşluk temizleme.
  • split(kalip): Metni regex'e göre parçalara ayırma (CSV, boşluk).

Örnek 2 (./Ornek2.java) e-posta/telefon doğrulama, kart maskeleme ($1), boşluk sadeleştirme ve CSV bölme gösterir.

Performans ve güvenlik

  • Önceden derle: Aynı kalıbı tekrar kullanacaksan Pattern.compilebir kez yap (alan olarak sakla); her seferinde derlemek pahalıdır. String.matches her çağrıda derler — döngüde kullanma.
  • Catastrophic backtracking: Bazı kalıplar (iç içe (a+)+ gibi) belirli girdilerde üstel yavaşlar. Kullanıcıdan gelen regex'lere veya karmaşık kalıplara dikkat et.

Özet

Regex'in metin arama/doğrulama/değiştirme dili olduğunu; Pattern/Matcher ile matches/find, metakarakterleri ve grupları (Örnek 1); doğrulama, replaceAll ile maskeleme ve split'i (Örnek 2) öğrendik; performans (önceden derleme) ve güvenlik (backtracking) notlarına değindik. Sırada, nesneleri byte'lara çevirip saklama/iletme: Serialization.

Kod Örnekleri(2)

Ornek1

çalıştırılabilir
Ornek1.java
1// Ornek1: Düzenli ifadeler (regex) — Pattern, Matcher, gruplar.
2// Çalıştırma: java Ornek1.java
3import java.util.regex.Matcher;
4import java.util.regex.Pattern;
5
6public class Ornek1 {
7
8    public static void main(String[] args) {
9        // matches: TÜM metin kalıba uyuyor mu? (String.matches kısayolu da var)
10        System.out.println("'12345' sadece rakam mı? " + "12345".matches("\\d+"));
11        System.out.println("'12a45' sadece rakam mı? " + "12a45".matches("\\d+"));
12
13        // find: metin İÇİNDE kalıbı arar (tüm eşleşmeleri gezer).
14        Pattern p = Pattern.compile("\\d+");           // bir veya çok rakam
15        Matcher m = p.matcher("oda 12, kat 3, daire 45");
16        System.out.print("Bulunan sayılar: ");
17        while (m.find()) System.out.print(m.group() + " ");
18        System.out.println();
19
20        // Gruplar: parantezlerle alt-parçaları yakala.
21        Pattern tarih = Pattern.compile("(\\d{2})\\.(\\d{2})\\.(\\d{4})");
22        Matcher tm = tarih.matcher("Doğum: 20.05.1995");
23        if (tm.find()) {
24            System.out.println("Tüm eşleşme: " + tm.group(0));
25            System.out.println("  gün=" + tm.group(1) + ", ay=" + tm.group(2) + ", yıl=" + tm.group(3));
26        }
27
28        // İsimli gruplar: okunaklılık
29        Pattern email = Pattern.compile("(?<kullanici>\\w+)@(?<alan>[\\w.]+)");
30        Matcher em = email.matcher("iletisim: ada@site.com");
31        if (em.find()) {
32            System.out.println("kullanıcı=" + em.group("kullanici") + ", alan=" + em.group("alan"));
33        }
34
35        System.out.println("""
36
37                --- Regex temelleri ---
38                Pattern.compile(kalip) -> Matcher ile metinde arama. matches (tümü), find (içinde).
39                Sık metakarakterler: \\d rakam, \\w harf/rakam/_, \\s boşluk, . herhangi,
40                  + (1+), * (0+), ? (0/1), {n,m} (aralık), ^ baş, $ son, [...] küme, (...) grup.
41                group(n): n. yakalama grubu; isimli grup: (?<ad>...) ve group("ad").""");
42    }
43}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

Ornek2

çalıştırılabilir
Ornek2.java
1// Ornek2: Regex ile doğrulama, değiştirme (replaceAll) ve bölme (split).
2// Çalıştırma: java Ornek2.java
3import java.util.Arrays;
4import java.util.regex.Pattern;
5
6public class Ornek2 {
7
8    // Önceden derlenmiş kalıplar (tekrar kullanılacaksa derleyip sakla -> performans).
9    static final Pattern EMAIL = Pattern.compile("^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$");
10    static final Pattern TC_TEL = Pattern.compile("^05\\d{9}$"); // 05XXXXXXXXX
11
12    public static void main(String[] args) {
13        // 1) Doğrulama
14        for (String e : new String[]{"ada@site.com", "gecersiz", "a@b.co"}) {
15            System.out.println("e-posta '" + e + "' geçerli mi? " + EMAIL.matcher(e).matches());
16        }
17        System.out.println("telefon '05321234567' geçerli mi? " + TC_TEL.matcher("05321234567").matches());
18
19        // 2) replaceAll — geri referansla ($1) maskeleme/biçimleme
20        String metin = "Kart: 1234 5678 9012 3456";
21        String maskeli = metin.replaceAll("\\d{4} \\d{4} \\d{4} (\\d{4})", "**** **** **** $1");
22        System.out.println("\nMaskelenmiş: " + maskeli);
23
24        // Fazla boşlukları teke indir
25        String temiz = "çok    fazla     boşluk".replaceAll("\\s+", " ");
26        System.out.println("Temizlenmiş: '" + temiz + "'");
27
28        // 3) split — regex'e göre böl
29        String csv = "elma, armut ,  kiraz ,muz";
30        String[] parcalar = csv.split("\\s*,\\s*"); // virgül + etrafındaki boşluklar
31        System.out.println("Bölme: " + Arrays.toString(parcalar));
32
33        System.out.println("""
34
35                --- Doğrulama, değiştirme, bölme ---
36                Doğrulama: pattern.matcher(metin).matches() ile format kontrolü (e-posta, telefon...).
37                replaceAll(kalip, yenisi): $1, $2 ile yakalanan grupları kullanarak değiştir (maskeleme, biçimleme).
38                split(kalip): metni regex'e göre böl (CSV, boşluk vb.).
39                İPUCU: tekrar kullanılan kalıpları Pattern.compile ile bir kez derle (her seferinde değil).
40                NOT: kullanıcıdan gelen regex'lerde 'catastrophic backtracking' (yavaşlama) riskine dikkat.""");
41    }
42}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.