PHP 8.4.2 Released!

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.

add a note

User Contributed Notes 1 note

up
2
Anonymous
2 years ago
Never put a "once-only subpattern" (?>...) in a "one-line" comment (#, //).
I spent almost 1 day to fix it.
Use a 'C' style comment instead !

PHP Manual says, a "one-line" comment (# , //) ends just before "?>" (PHP end tag).

These letters "?>" in a "one-line" comment (# , //) seems evaluated as a PHP end tag.

<?php

/* (?> */
echo '"C" style comment works !<br>';

# (?>
echo '"one-line" comment';

?>
To Top