Sadece bir kerelik alt şablonlar
Yinelemeyi gerek asgarileştirirken gerekse azamileştirirken, yineleme
sayısının her değiştirilişinde ana şablonun kalanının eşleştiğini
görmek için yapılan değerlendirmedeki başarısızlık normal olarak bu
işlemin yinelenmesine sebep olur. Eşleşmenin doğasını değiştirerek veya
şablonun yazarı numaralı eşleşmenin mümkün olmadığı noktayı biliyorsa
eşleşmenin vaktinden önce başarısız olmasını sağlamak suretiyle bazen
bunun olmasını engellemek yararlı olabilir.
\d+foo şablonunun 123456bar
satırına uygulandığını
varsayalım.
Eşleşterici, ilk altı rakamı eşleştirdikten sonra "foo" ile eşleşmenin
mümkün olmadığını görünce, eninde sonunda başarısız olmadan önce
şablonun \d+ parçasını önce 5 rakamla, sonra 4 rakamla, vb.
eşleştirmeyi dener. Sadece bir kerelik alt şablonlar, şablonun belli
bir parçasınının sadece bir kere eşleştirileceğini belirten alt
şablonlardır. Böylece eşleştirici "foo" ile ilk eşleştirme denemesinin
hemen ardından başarısız olur. Alt şablonun sözdizimi, aşağıdaki
örnekte olduğu gibi (?> ile başlayan yaylı ayraçlı alt şablonların
özel bir çeşididir: (?>\d+)bar
Eşleştiriciyi azami sayıda eşleşmeye kilitleyen bu çeşit alt şablonlar
bir kerelik eşleşme sağlarlar ve şablonun tamamını eşleştirmedeki ilk
başarısızlıkta şablonun geriye saymasını engellerler. Ancak, şablonun
diğer parçaları geriye saymayı gerektiriyorsa bu normal olarak çalışır.
Başka bir deyişle, bu tür bir alt şablon, eşleşmeye konu dizgenin belli
bir noktasına demirlemenin mümkün olduğu bir durumda tekil bir şablonun
eşleşeceği dizgeyle eşleşir.
Sadece bir kerelik alt şablonlar, yakalamayan alt şablonlardır.
Yukarıdaki örnekteki gibi basit durumlar, kalan herşeyin tüketilmesine
sebep olan bir yineleme azamileştirmesi olarak düşünülebilir. Bu
bakımdan, \d+ ve \d+? şablonlarının ikisi de şablonun kalanını
eşleştirmek için rakam sayısını ayarlamaya çalışırken, (?>\d+)
şablonu rakam dizisinin tamamıyla sadece bir kere eşleşebilir.
Bu oluşum, şüphesiz keyfi olarak karmaşıklaştırılmış alt şablonlar
içerebilir ve bunlar iç içe olabilir.
Sadece bir kerelik alt şablonlar, dizge sonuyla etkili bir eşleşme
belirtmek için, geriye bakan sav alt şablonları ile birlikte
kullanılabilir. Eşleşmeyeceği uzun bir dizgeye uygulanacak, basit bir
şablon olarak abcd$
şablonunu ele alalım. İşlem
soldan sağa doğru uygulanacağından, PCRE, eşleşmeye konu dizgedeki her
"a" için şablonun kalanıyla bir eşleşme arayacaktır. Eğer şablon,
^.*abcd$
olarak belirtilirse, ilk olarak baştaki .*
dizgenin tamamıyla eşleşir, fakat bu başarısız olursa (dizgenin ardında
bir "a" bulunmaması durumu), önce son bir karakteri bütün dizgeyle
eşleştirmek için dizgede geriye gitmeye başlar, sonra bunu son iki
karakter için ve son üç için, vb. dener. Dolayısıyla, "a" için
dizgenin tamamıyla eşleşmeyi sağlayacak taramanın bu kez sağdan sola
sola uygulanmasından başka değişen bir şey olmayacaktır. Bununla
birlikte, şablon, ^(?>.*)(?<=abcd)
olarak
yazılırsa .* için geriye doğru defalarca eşleştirme denemesi yerine,
dizgenin tamamıyla bir kerede eşleşme denenebilecektir. İkinci grupta
belirtilen geriye bakan sav, son dört karakterin üzerinde sadece bir
deneme yapacak, eğer eşleşme sağlanamazsa eşleştirici başarısız
olacaktır. Uzun dizgeler sözkonusu olduğunda bu yaklaşım işlem süresi
üzerinde önemli bir fark yaratacaktır.
Bir şablonun sınırsız sayıda yineleme içeren bir alt şablonu olması
durumunda şablonun tamamı için sınırsız sayıda eşleşme denenecek
demektir; eşleşme başarısızlığının çok uzun bir sürenin sonunda
alınmasından kaçınmanın tek yolu ne yazık ki, sadece bir kerelik alt
şablon kullanımıdır. (\D+|<\d+>)*[!?]
şablonu,
gerek hiç rakam bulunmaması gerekse rakamların <> ile sarmalanması
durumunda, ardından ! veya ? belirtilmesi nedeniyle, sınırsız sayıda
alt dizge ile eşleşecektir. Eğer eşleşme olursa işlem çabucak
bitecektir. Bununla birlikte, şablon,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
dizgesine uygulandığında başarısızlığın raporlanması çok uzun
zaman alacaktır. Bunun sebebi, dizgenin çok sayıda yolla iki yinelemeye
bölünebilmesi ve hepsinin denenmesidir. (Hem PCRE hem de Perl'in, tek
bir karakter kullanıldığında hızlı bir başarısızlığa izin vermesi
nedeniyle, örnekte sondaki tek karakter yerine [!?] kullanılmıştır. Bir
eşleşme için son tek karakterin varlığı gereklidir ve dizgede
bulunmazsa erken bir başarısızlık söz konusudur.) Eğer şablon,
((?>\D+)|<\d+>)*[!?]
olarak değiştirilirse, rakam
bulunmayan dizgeler bölünemeyecek ve başarısızlık çabucak
gerçekleşecektir.