Düzenli İfadeler

^.+@.+\..+$ işaretlerinin,
Düzenli İfade işlemlerine ait olduğunu belirtilim. Bu işaretler ve
onların arasına koyduğumuz karakter örnekleri ile, PHP”nin aradığımız
bir metnin karakterlerinin hangi diziliş, sıralanış konumunda olduğuna
bakarak, bize o metni bulmasını sağlarız; ya bu metni kullanırız,
sileriz veya değiştiririz. Dolayısıyla, Düzenli İfade demek, bir
diziliş, sıralanış biçimi demektir.

Eşleştirme deyimleri ve işaretler
PHP”nin
karakter ve sıralanış eşlemede kullanılan düzenli ifade komutlarını
kısaca ele alalım; sonra bunları kullanmamıza imkan veren fonksiyonları
görelim.

^hakk       =>  “hakk” ile başlayan bütün kelimeleri bulur.

edilemez$      =>  Bu deyim ise PHP”ye “edilemez” ile biten bütün kelimeleri bulur

^hakkı$      =>  PHP,
başında ^ işareti, sonunda $ işareti bulunan kararter sıralanışını,
aynen arar; yani bu deyim, birinci örnekteki üç cümleyi de bulamaz.

Hakk      =>  Bu deyim ise her üç cümleyi de buldurur; çünkü üçünde de bu dört karakter bu sıralanışla mevcuttur.

PHP”nin
Düzenli İfadeleri, bütün rakam ve harfleri eşleştirebilir. Fakat sorun,
özel karakterlerde çıkar. Sözgelimi, sekme işareti, satır sonlarında
yeni-satır/satırbaşı işareti, gibi özel karakterleri, ancak önlerine
Escape işareti olan ters bölü işaretini koyarak buluruz.

Düzenli İfadelerde Özel Karakterler

[]   Geri (Backspace) karakterini bulur.
     Belirtilen
karakterle sınırlanan kelimeyi bulur: k, “hak mücadelesi”
ifadesindeki birinci k”yı bulur; çünkü bu harf, bir kelime
sınırlayıcıdır.
B     Belirtilen karakterle sınırlanmayan kelime yoksa, başlayanı bulur: kBi, “üç kişi” ifadesindeki “ki”yi bulur.
cX   X yerine yazacağımız kontrol karakterini bulur. Örneğin, cA, Ctrl+A”yı, cZ ise Ctrl+Z”yi bulur.  
d    
0″dan 9″ya kadar bir rakamı bulur: IEd, her ikisi de herhangi bir
rakamla biten “IE5″ ve “IE4″ değerlerini ikisini de bulur,
D    Herhangi bir ondalık işaretini bulur.
f     Form-feed (kağıt çıkart) karakterini bulur.

    Newline (yeni satır) karakterini bulur.

    Return (satırbaşı) karakterini bulur.
s    Boşluk (space) bulur.
S   Yatay ve düşey sekme, kağıt-çıkart, yeni satır, satırbaşı ve boşluk dışındaki herhangi bir karakteri bulur.
    Yatay sekme (Tab) karakterini bulur.
v    Düşey sekme karakterini bulur.
w   Herhangi bir harf, rakam veya alt-çizgiyi bulur.
W  Harf, rakam ve alt-çizgi dışındaki karakteri bulur.
xHex Verilen 16 tabanlı (Hexadecimal) sayıya uygun Escape karakterini bulur. Örneğin,
25, % işaretini bulur. 

Bu
arada noktalama işaretlerini arattırırken, önlerine ters bölü işareti
koymak gerekir. Ters bömü işaretini de yine önüne ters bölü işareti
koyarak (\) arttırabilirsiniz.

Karakter Grupları

PHP”nin
Düzenli İfadeleri”nde kolaylık sağlayan ve mesela ziyaretçinin bir
Form”da bir INPUT etiketine verdiği yanıtıların içinde olmaması veya
olmaması gereken karakterleri bulmamıza imkan veren karakter grupları
oluşturma yöntemini de kullanabiliriz. Sözgelimi bütün sesli hafleri
aratmak için şöyle bir karakter grubu oluşturabiliriz:

[OoUuÖöAaOoEeıIiİ]

Karakter
gruplarını köşeli parantez içinde yazarız. Bu deyimle, PHP, içinde
herhangi bir sesli harf bulunan bütün değerleri eşleştirecektir. Bu
yöntemden yararlanarak, şu grupları kullanabiliriz:

[a-z]        Herhangi bir küçük harfi bulur.
[A-Z]        Herhangi bir büyük harfi bulur.
[a-zA-Z]   Herhangi bir büyük veya büyük harfi bulur.
[0-9]        Herhangi bir rakamı bulur.
[0-9.-]   Herhangi bir rakamı, noktayı veya kesme çizgisini bulur.
[ f

]  Herhangi bir Form-feed (kağıt çıkart), Newline (yeni satır), Return (satırbaşı) karakterini veya  boşluğu (space) bulur.

Sözgelimi,
bir alfanümerik değer kümesinde b3, u2, n9 gibi birincisi küçük harf,
ikincisi rakam olan iki karakterlik dizileri bulmak istiyorsak, arama
grubunu şöyle kurarız:

^[a-z][0-9]$     =>    Bu
deyim PHP”ye, a”da z”ye küçük harfle başlayan, (^işareti aranan unsurun
değerin başında olması gerektiğini söylüyor) ve sonunda 0″dan 9″a bir
rakam bulunan kelimeleri bulmasını söyleyecektir. PHP, bu kelimenin
sadece iki harfli olmasına dikkat edecektir; çünkü grubumuzun bir başı
ve bir de sonu belirlendiğine göre, üç karakterli değerlerin bulunması
imkanı yoktur.

^
işareti köşeli parantez içinde grup deyimi oluştururken kullanılırsa,
bu olumsuzluk anlamı taşır. Sözgelimi, iki rakamlı ancak birinci
karakteri rakam olmayan fakat ikinci karakteri rakam olan değerlerin
bulunması için şu deyim gerekir:

^[^0-9][0-9]$   =>     Burada
en baştaki ^işareti “başında” demektir; ancak hemen arkasından gelen
grupta “rakam olmayan” demiş oluyoruz; ikinci grup ve sonundaki $
işareti ile “rakamla biten” anlamına geliyor. Deyimde sadece baş ve
sonu gösteren iki eşleştirme unsuru bulunduğuna göre bu deyim, “başında
rakam olmayan, sonunda rakam olan iki karakterli değerleri” bulmaya
yarayacaktır. Bu deyim söz gelimi 13″ü bulmayacak, fakat u2″yi
bulacaktır. Bu yöntemle şu grupları yapabiliriz:

[^a-z]       Küçük harf olmayan herhangi bir harfi bulur.
[^A-Z]       Büyük harf olmayan herhangi bir harfi bulur.
[^\/^]   , / veya ^ dışında herhangi bir karakteri bulur.
[^""]       Çift ve tek tırnak dışında herhangi bir karakteri bulur.

Grup
oluşturmada kullandığımız özel karakterler de vardır. Örneğin nokta
işareti (.), yeni satır başlangıcı olmayan herhangi bir karakter
anlamına gelir. Dolayısıyla,

^.0$     =>     deyimi yeni satırla başlamayan ve sıfır ile biten herhangi iki karakterli değeri bulacaktır.

Karakter
eşleştirmede tekrar sayısı da bir özellik olarak kullanılabilir. Tekrar
sayısı belirtmek için süslü parantez ({}) kullanırız.

Örnekler:

^a{4}$                    İçinde sadece dört adet küçük a harfi bulunan kelimeleri seç: aaaa.
^a{2,4}$                  İçinde sadece iki üç veya dört adet küçük a harfi bulunan kelimeleri seç: aa, aaa, aaaa gibi
^a{2, }                
   İki veya daha fazla küçük a harfi bulunan kelimeleri seç: haar,
haaar, haaaar gibi. Bu deyim “har” kelimesini seçmez.
{2}                        Ardarda iki sekme işaretini bul
.{2}                         Herhangi çift karakteri bul: aa, &&, == gibi
^-{0,1}[0-9]{1,}$    Negatif veya pozitif herhangi bir tam sayıyı bul
^[0-9]{1,}$              Pozitif herhangi bir tam sayıyı bul

Bu tür deyim oluşturma işlemleri giderek karmaşıklaşabilir. Örneğin:

^-{0,1}[0-9]{0, }.{0,1}[0-9]{0, }$

Bu
karmaşık deyim aslında sadece “Negatif veya pozitif bir ondalık
(double) değeri bul,” anlamına geliyor. Kısaca irdelersek, aranan
degerin sıfır veya bir kere tekrarlanan bir kesme çizgisiyle
başlayabileceğini (”Sıfır veya bir kere” demek, olsa da olur, olmasa da
anlamına geliyor!) bunu sıfır veya daha fazla kere tekrarlanan bir
rakamın izleyebileceğini, onu da sıfır veya bir kere tekrarlanan bir
nokta işareti ile sonunda sıfır veya daha fazla kere tekrarlanan
herhangi bir rakamın izleyebileceğini söylemiş oluyoruz.

PHP bu tür karmaşık ifadelerin hatasız yazılmasını sağlayan kısayollara sahiptir. Bunları sıralayalım:

  ?    
 {0,1} anlamına gelir. Kendisinden önce yer alan unsurun en az sıfır en
çok bir kere tekrar edilmesi gerektiğini (olmayabileceğini ama olursa
en fazla bir kere olabileceğini) belirtir.

  *   
 {0, } anlamına gelir. Kendisinden önce yer alan unsurun sıfır veya
daha fazla kere tekrar edilmesi gerektiğini (tümüyle opsiyonel
olduğunu) belirtir.

  +   
 {1, } anlamına gelir. Kendisinden önce yer alan unsurun en az bir veya
daha çok kere tekrar edilmesi gerektiğini (bulunmasının zorunlu
olduğunu) belirtir.

Bu kısa-yolları kullanarak, yukarıdaki karmaşık ifadeleri basitleştirelim:

^[a-zA-Z0-9_]+Ş            En az bir harf veya rakam veya altçizgi içeren herhangi bir kelime
^[0-9]+Ş                       Herhangi bir pozitif tamsayı
^-?[0-9]+Ş                   Herhangi bir tamsayı
^-?[0-9]*.[0-9*$]+Ş    Herhangi bir kesinli (double) sayı

Bir
Düzenli İfade”nin yazılışında birden fazla arama-sıralanış deyimine yer
verebiliriz. Bunu yapmamızı sağlayan | işaretidir. Örneğin,

.com|.co.uk

ifadesi
ile, ya “.com” ya da “.co.uk” değerlerinin bulunmasını sağlayabiliriz.
Burada | işareti “veya” kelimesi gibi düşünebilirsiniz.

Düzenli
ifadeler yoluyla INPUT etiketinden gelen değerleri incelerken hata
yapmak kolaydır. Bunun için kendi ifadelerinizi mutlaka sçeşitli
olasılıklara karşı sınamalısınız. Bu bölümün başında örnek olarak
verdiğimiz Düzenli İfade”yi hatırlıyor musunuz?

^.+@.+\..+$

Örneğin
bu ifade, ziyaretçinin elektronik posta adresini yazması gereken bir
INPUT etiketinin sağladığı değerin gerçekten elektronik adres biçimi
taşıyıp taşımadığını sınar. Baştaki ^ ve nokta işaretleri ile artı
işareti değerin önünde boşluk olmamasını sağlıyor; @ işareti ise
değerin içinde @ bulunması gerektiğine işaret ediyor. Tekrar eden nokta
ve artı işaretleri “ne kadar olursa olsun ve ne olursa olsun” anlamına
geliyor. Bunu izleyen nokta karakterini gösteren (.) işaret buralarda
bir de gerçekten nokta olması gerektiğini ve bunu izleyen nokta ve artı
tekrar “ne olursa olsun, ne kadar olursa olsun” anlamını taşıyor. Başka
bir deyişle, aradığımız değerin “herhangi bir şey” @ “herhangi bir şey
daha” . “birşeyler daha” şeklinde olduğunu belirtmiş oluyoruz. Ne var
ki deyimiçinde iki nokta veya iki @ işareti olan veya @ işareti ile
nokta arasında bir şey bulunmayan veya @ veya noktadan öncesi ya da
sonrası boş olan bütün değerleri safdışı etmeye yetmeyecektir.

Düzenli İfade Fonksiyonları

Yukarıda
öğrendiğimiz Düzenli İfade yazma tekniklerini, PHP”nin bize sağladığı
beş fonksiyonda parametre olarak kullanırız. PHP”nin ayrıca Perl-tarzı
düzenli ifade fonksiyonları da vardır. Bu fonksiyonlardan, ya bize bir
boolean (doğru/yanlış) değer döner; ya da fonksiyon istediğimiz işi
yaparak vardığı sonuçları verdiğimiz değişkene yazar. Biz, daha sonra
bu değere bakarak veya değişkenin değerlerini kullanarak, PHP
programımızın akışını kontrol edebiliriz. Burada ele alacağımız
fonksiyonlara ilişkin örneklerde, daha önceki bölümlerde oluşturduğumuz
konuk defteri programı ile Web ziyaretçilerimizin sunucuya göndereceği
bilgileri doğrulamaya ve muhtemel zararlı kodlardan ayıklamaya
çalışacağız.
 
 ereg() ve eregi()

PHP”nin
temel Düzenli İfade Fonksiyonu, ereg(), arattığımız karakter sıralanışı
bulunduğu taktirde doğru, bulamadığı taktirde yanlış karşılığı bir
değer verir. Fonksiyonu şöyle yazarız:

$bir_degisken = ereg(”eşleştirilecek_sıra” , $kaynak , $yeni_değişken);

Fonksiyonun
aradığımız eşleştirmeyi yapması halinde, buradaki $bir_degisken”in
değeri true/doğru, yapamaması halinde false/yanlış olacaktır.
Eşleştirme sırasının nasıl oluşturulduğunu yukarıda gördük; bu
ifadelerden işimize uygun olanı buraya tırnak içinde yazarız. $kaynak,
eşleştirilecek sıralamanın içinde aranacağı değeri tutan değişkendir.
Fonksiyonun bir diğer becerisi, eğer eşleştirilecek sıralamayı gruplar
halinde verirsek, kaynakta yapacağı eşleştirme olursa, buna uygun
değerleri bir dizi değişkene yazabilmesidir; istersek bir parametre
olarak bu yeni değişkenin almasını istediğimiz adı veririz; böylece
eşleştirme sonucu bulunan değerler kaydedilmiş olur.

eregi(), aynen ereg() fonksiyonu gibi çalışır; sadece eşleştireceği değerlerde büyük-harf/küçük-harf farkı gözetmez.

Daha
önceki bölümde oluşturduğumuz ve kd_01.php adıyla kaydettiğimiz konuk
defteri programının akış planını, ziyaretçinin Form”a yazdığı ve
sunucuda $HTTP_POST_VARS dizi-değişkeninde tutulan değişkenlerinden
elektronik posta adresi ilge ilgili olanı gerçekten içinde en az bir @
işareti ile en az bir adet nokta içip içermediğine bakarak
sınayabiliriz. Böyle bir sınama için gerekli kod şöyle olabilir:

if (eregi(”^.+@.+\..+$“, $adres, $email)) {
 }
 else { 
 $hata = “Elektronik posta adresinizde bir hata var!<br>”;
   echo $hata;
   include(”kd_hata_halinde.htm”);
   exit;
 }

Program,
bu örnekte $adres değişkeninde kayıtlı değerin içinde aradığı
sıralamayı bulursa, eşleşen değeri $email adlı yeni bir değişkene
yazacak ve if sınavının sonucu doğru olacaktır. Bu sıralamaya uygun bir
değer bulunamazsa, if sınavı else deyimine atlayacak ve bir hata mesajı
üretilerek, bu program durdurulacaktır.

ereg_replace() ve eregi_replace()

Gördüğümüz
gibi, ereg() arattığımız karakter sıralanışı bulunduğu taktirde doğru,
bulamadığı taktirde yanlış karşılığı verdikten sonraduruyor! Oysa kimi
zaman arattığımız ve bulunan değerin başka bir değierle değiştirilmesi
gerekebilir. Bunun için ereg_replace() ve eregi_replace()
fonksiyonlarını kullanırıız:

ereg_replace(”eşleştirilecek_sıra” , yeni_metin , $kaynak);

Fonksiyonun
aradığımız eşleştirmeyi bulursa, bu değerin yerine verdiğimiz yeni
metni koyacaktır; yeni metni bir değişkenin değeri olarak da
verebiliriz. Uygulama örneği için yine konuk defteri örneğine dönelim.
Ziyaretçilerimiz kimi zaman yanlışlıkla, kimi zaman pek de iyi niyet
sonucu olmadan, kendilerinden beklediğimiz isim, adres ve mesaj yerine
sunucu veya başka ziyaretçilerin Browser programları tarafından kod
gibi algılanacak metinler yazabilirler. Burada sadece bu tür zararlı
metinlerin genellikle programlarda bulunması gereken karakterler
içerdiğini söylemekle yetinelim. Bu tür karakterlerin başında < ve
> işaretleri bulunur! Dolayısıyla, biz de ziyaretçimizden gelecek
verilerin yazıldığı değişkenlerin değerlerinde bu işaretleri aratabilir
ve  bunları içi boş bir alfanümerik değer ile değiştirebilir; yani
silebilir. Zararlı olabilecek kodların arasında daha bir çok karakter
bulunabilir; ancak Script diliyle yazılması gereken bu kodlardan <
ve > işaretlerini kaldırılması kodları işlemez hale getireceği için,
şu aşağıdaki örnek yeterli olabilir:

 $adi = ereg_replace(”<”,”",$adi);
 $adi = ereg_replace(”>”,”",$adi);
 $adres = ereg_replace(”<”,”",$adres);
 $adres = ereg_replace(”>”,”",$adres);
 $mesaj = ereg_replace(”<”,”",$mesaj);
 $mesaj = ereg_replace(”>”,”",$mesaj);

Burada
ereg_replace() fonksiyonu, ziyaretçiden gelecek üç değişkenin
değerlerinde < ve > işaretlerini aramakta onların yerine içi boş
bir metin (”") yazmaktardır.

split()

Düzenli
İfade ile çalışan bu fonksiyon, vereceğimiz eşleştirme sıralamasını
sınırlayıcı olarak kullanarak, belirteceğimiz değerde bulduğu değer
parçalarını ayırır ve bunları ayrı ayrı bir dizi değişkenin elemanları
olarak kaydeder. Bu fonksiyonu şöyle yazarız:

$yeni_dizi_değişken = split(”eşleştirilecek_sıra” , $kaynak, sınır_sayısı);

Fonksiyon,
aradığı sıralamayı bulamazsa, false/yanlış sonucunu verir. Burada sınır
sayısı olarak vereceğimiz rakam, oluşturulacak yeni dizi değişkene en
fazla kaç eleman yazılmasını istediğimizi gösterir. Bu sayıyı
vermezsek, PHP yeni dizi değişkenin gerektiği kadar elemana sahip
olmasını sağlar. Bir örnek vererek, bu fonksiyonu nasıl
kullanibileceğimizi görelim:

$metin = “İnsan sözüyle kendini gösterir, davranışlarıyla ruh halini aksettirir.”;
$aranan = ” “;
$yeni_dizi_değişken = split($aranan, $metin);
foreach ($yeni_dizi_değişken as $eleman) {
print “$eleman <br>”;
}

Bu
programda PHP, $metin değişkeninin içerdiği değerde $aranan
değişkeninin içerdiği değeri, yani boşluğu, eşleştirilecek unsur olarak
kullanacak ve $metin değişkeninin değerini boşluklarından parçalara
ayıracaktır. Ayrılıcak her yeni parça, $yeni_dizi_değişken adlı
değişkenin elemanları olarak atanacaktır. Programın geri kalan kısmı
ise, bu yeni dizinin elemanlarını görüntülemekterdir.

 sql_regcase()

İçinde
büyük harf-küçük harf ayrımı olan bir değeri büyük harf-küçük harf
ayrımı olmayan Düzenli İfadeler haline çevirir. Bu fonksiyon bizden
Düzenli İfade almaz, tersine Düzenli İfade oluşturur. Örnek:

<?php
$metin = “Sözler”;
echo(sql_regcase($metin);
?>

Bu program, Browser penceresine şu metni yazdırır:
[Ss][Öö][Zz][Ll][Ee][Rr]