
Regex’te açgözlü ve tembel eşleştirme: Deseniniz neden gereğinden fazla karakteri kapsıyor?
Yayın Tarihi 24 Tem 2026
Kalın etiketinin içeriğini almak için <b>.*</b> yazarsınız, bunu <b>Hello</b> üzerinde denersiniz, mükemmel şekilde çalışır. Ardından, aynı satırda iki kalın etiket içeren gerçek bir HTML dosyasında bunu çalıştırdığınızda — <b>Hello</b> and <b>World</b> — iki eşleşme yerine, her iki etiketi de kapsayan tek bir devasa eşleşme elde edersiniz. Bu, düzenli ifade motorunuzdaki bir hata değildir; *, + ve {n,m}’in varsayılan davranışıdır ve ne olduğunu anladığınızda tek karakterlik bir düzeltmeyle çözülebilir.
Neden .* beklediğinizden fazlasını yakalar?
Varsayılan olarak, düzenli ifadelerindeki nicelik belirleyiciler açgözlüdür — .* “bazı karakterlerle eşleş” anlamına gelmez; “mümkün olduğunca çok karakterle eşleş, ardından desenin geri kalanı kesinlikle gerektirdiği takdirde geri çekil” anlamına gelir.
<b>.*</b> ile <b>Hello</b> and <b>World</b> arasındaki farkı adım adım inceleyelim:
<b>, ilk<b>ile eşleşir..*, dizenin geri kalanının tamamını tüketerek başlar — ikinci<b>World</b>dahil olmak üzere sonuna kadar her şeyi.- Motor, eşleşmeyi tamamlamak için
</b>’i bulması gerektiğinden,.*’in sonundan bir karakter bir karakter geriye doğru taramaya başlar. </b>’in sığabileceği ilk konum (sonundan geriye doğru taranırken), dizgedeki en sondaki</b>’tir — “mantıken” durması gereken ilk konum değildir.
Dolayısıyla eşleşme, <b>Hello</b> and <b>World</b> dizisinin tamamı olarak sonuçlanır; çünkü açgözlü eşleştirme her zaman mümkün olan en uzun dizgiyi önce dener ve kalıbın geri kalanının başarılı olması için sadece gerekli olduğu kadar küçültür.
Çözüm: ? ile niceleyiciyi tembel hale getirin
Bir niceleyicinin hemen arkasına ? eklemek, onu açgözlüden tembel (aynı zamanda “açgözlü olmayan” veya “isteksiz” olarak da adlandırılır) hale getirir: *?, +?, ??, {n,m}?.
Tembel bir niceleyici ise tam tersini yapar: mümkün olduğunca az karakterle eşleştirmeye başlar, ardından desenin geri kalan kısmı henüz başarılı olamıyorsa genişler.
Aynı dizeye karşı <b>.*?</b>:
<b>, ilk<b>ile eşleşir..*?, sıfır karakter ile eşleştirerek başlar.- Motor şunu kontrol eder:
</b>tam burada eşleşiyor mu? Hayır (şu anda “Hello…” kısmındayız, henüz</b>kısmında değiliz) — bu nedenle.*?’i tam olarak bir karakter genişletir ve tekrar kontrol eder. - Bu işlem,
.*?tam olarakHello’i tüketene kadar karakter karakter tekrarlanır; bu noktada</b>hemen eşleşir.
Sonuç: <b>Hello</b> ve <b>World</b> iki ayrı eşleşme olarak geri döner; bu, etiket benzeri veya sınırlayıcı benzeri yapıları ayrıştırırken neredeyse her zaman istediğiniz şeydir.
Gerçekten açgözlü eşleştirme istediğiniz durumlar (bu sadece “yanlış varsayılan” değildir)
Açgözlü eşleştirme, dilde bir hata değildir — farklı, aynı derecede yaygın bir durum için doğrudur: bir şeyin en dıştaki sınırını eşleştirmek, içindeki en küçük birimi değil. JSON benzeri bir metin yığınında “ilk { ile son } arasındaki her şeyi” ayıklıyorsanız (örneğin, iç içe geçme durumuna bakılmaksızın bir nesnenin tamamını almak için), greedy tam olarak doğru seçimdir; oysa lazy, bunun yerine ilk iç } ’de durur ve size kesik, geçersiz bir parça verir.
Genel kural: tekrarlanan küçük, sınırlandırılmış parçalar için lazy (etiketler, tırnak içine alınmış dizeler, liste öğeleri); “dıştaki tüm aralığı al” için greedy.
Hızlı başvuru
| Desen | Davranış | Ne zaman kullanılır |
|---|---|---|
.*, .+, {n,m} |
Açgözlü — mümkün olan en uzun eşleşmeyi bulur | En dıştaki aralığı istiyorsanız veya dizgede yalnızca bir eşleşme varsa |
.*?, .+?, {n,m}? |
Tembel — mümkün olan en kısa eşleşmeyi bulur | Birbirine benzeyen, sınırlayıcılarla ayrılmış birden fazla parça varsa ve her birini ayrı ayrı almak istiyorsanız |
Bir kalıbın test dizesi yerine gerçek girdinizde aslında hangisini yaptığından emin değilseniz, canlı eşleşme vurgulamalı bir regex tester üzerinde çalıştırırsanız, eşleşmelerin anında vurgulanması sayesinde farkı hemen görebilirsiniz — açgözlü (greedy) yöntemde tek bir büyük vurgulanmış blok görürken, tembel (lazy) yöntemde birkaç ayrı blok görürsünüz; bu, karakter karakter incelemeye kıyasla genellikle daha hızlıdır.