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
| Sembol | Anlamı | Sembol | Anlamı | |
|---|---|---|---|---|
\d | rakam | + | bir veya çok | |
\w | harf/rakam/_ | * | sıfır veya çok | |
\s | boş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.compile'ı bir kez yap (alan olarak sakla); her seferinde derlemek pahalıdır.String.matchesher ç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ılabilir1// 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}Ornek2
çalıştırılabilir1// 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}