09-01-2015, 05:04 AM
Regular expression (regex) Türkçesiyle ''düzenli ifadeler'' metinlerde bir biçimsel dil kullanarak tarif edilen kısımları seçip ayırmamıza yarayan bir programdır.
Neredeyse bütün programlama dillerinde kullanılan ''regex'' ile metinlerde ayrıştırmak istediğiniz her şeye ulaşabilirsiniz.
Örneğin günümüzde en çok içerik çalma botlarında kullanılır. Fakat yazı düzeni sağlamak ya da metinlerde aranan ifadelere ulaşıp onları manipüle etmek için de kullanabilirsiniz.
Giriş:
Yazı boyunca anlatılan desenleri deneyebilmek için anlık işlemler yapabilen ve her ''regex'' çalışmanızda tarayıcınızın bir tabında açık olması gereken bu siteleri mutlaka yer imlerinize eklemeniz tavsiye edilir.
- Regex101 (tavsiye edilir)
- Rubular
- Gethifi Regexp Tool
- RegExr
RegEx ile yapılabilecek en basit işlem kelime aramaktır, bunun için direkt aramak istediğimiz kelimeyi yazmak yeterli. Örnek olarak düzenli ifademize “mybb” yazıyoruz. Ve elde edeceğimiz sonuçta elma kelimelerinin seçildiğini görebilirsiniz.
Örnek Düzenli İfade:
mybb
Metin ve Sonuç:
Bu deneme amaçlı yazılmış ve içerisinde mybb geçen öylesine bir metin.
Yukarıda yeşil renkle işaret edilen kelime, yazdığımız ifadenin yakaladığı kelimenin göstergesidir. Bundan sonraki örneklerde de elde ettiğimiz sonuçları böyle göstereceğim.
Özel karakterler:
Düzenli ifadelerde bolca anlam ve ifade içeren özel karakterler vardır. Asıl yapmak istediklerimizi bunlarla ifade edip istenilen sonuca ulaşırız. Öncelikle bu karakterlerin ne olduklarına bakalım, sonrasında da nasıl kullanıldıklarını örnekler ile deneyelim.
Düzenli İfadelerde Kullanılan Özel Karakterler:
Regex Ayarları:
Regex desenleri iki “/” (bölü) işaretinin arasına yazılır. Sondaki bölü işaretinden sonra isteğe bağlı olarak ''regex ayar karakterleri'' girilir.
Ayar Karakterleri:
Örnek kullanımı:
PHP Kod:
Kod:
/mybb/i
Bu örnekte büyük MYBB, küçük mybb ya da Mybb şeklinde yazılanları da büyük küçük harfe aldırmadan yakalar.
Yukarıdaki örnek mybbci, mybbmod gibi kelimelerin içerisindeki “mybb”leri de bulacaktır. Eğer sadece mybb kelimesini aramak istiyorsak kelime başı ve sonunu ifade eden \b kullanacağız.
Örnek:
PHP Kod:
Kod:
/\mybbci\b/gi
Şimdi sadece mybb kelimesini bulacağız, mybbci, mybbmod gibi diğer mybb içeren kelimeleri yakalamayacaktır.
Sayıları Yakalamak:
Gelelim şimdi yukarıdaki tabloda listelediğimiz karakterlerin örnek kullanımına. Girilen içerikte sadece sayıları bulmak için “\d” ve “+” karakterlerini kullanacağız.
Örnek kullanımı:
PHP Kod:
Kod:
/\d+/g
Bu örnek sadece 1234, 321, 789 sayılarla eşleşir. “g” ayarı ile de bir kere değil kapsamlı aramasını ifade ettik
Bir veya daha fazla tekrarı ifade eden “+” karakterinin başına herhangi bir rakamı ifade eden “\d” yazdık. Daha işe yarar bir örnek için girilen içerikteki tarih formatında yazılmış ifadeyi yakalayalım.
Örnek:
PHP Kod:
Kod:
/(\d{2}\.\d{2}\.\d{4})/g
İfadenin karışık görünmesi sizi korkutmasın, ilgili yerlerden inceleyerek ayıkladığınızda ne olduğunu daha rahat özetleyebilirsiniz. \d{2} 2 rakamı, sonrasında \. kaçış karakteri ile noktayı, son kısımda ise 4 rakamı ifade ettik. Böylece20.08.2014 gibi bir içerikle eşleşecektir.
Kelimeleri Yakalamak:
Bunun için yukarıdaki örnekle benzer bir ifade ile yapabiliriz.
Örnek Kullanımı:
PHP Kod:
Kod:
/(\w+)/g
\w ifadesi herhangi bir harfi ifade ettiğini söylemiştik fakat Türkçe karakterlerin bu ifade için istisna olduğunu bilmeniz gerekiyor. Eğer Türkçe bir içerikle çalışıyorsak yapmamız gereken ifade şöyle olmalı;
Örnek:
PHP Kod:
Kod:
/([a-zA-ZÇŞĞÜÖİçşğüöı]+)/g
Bu ifade ile Türkçe kelimeleri de yakalayabiliriz.
Küçük ve büyük a’dan z’ye harlerin yanına Türkçe’de olan küçük ve büyük harfleri ekledik. Bir diğer örnek olarak da içerikten sadece istenilen bir kelimeyi almayı deneyelim.
Örnek:
PHP Kod:
Kod:
/benim adım (\w+)/gi
Merhabalar benim adım XpSerkan!
Başlangıç ve Sona Göre Yakalama:
^ ve $ karakterleriyle başının ya da sonunun nasıl olacağını ifade edebiliriz. Örnek olarak sadece ''selam'' ile başlayan içeriği ayıklamayı deneyelim.
Örnek Kullanımı:
PHP Kod:
Kod:
/^selam/
Bu örnek metin ''selam'' ile başlamadığı için hiç bir şeyle eşleşmeyecektir
selam! bu örnek daha samimi olduğu için eşleşecektir
''Selam'' ile başlayan ve ''hoşçakal'' ile biten metnin arasında geçenleri yakalayacak bir örnek daha;
Örnek:
PHP Kod:
Kod:
/^selam(.+)hoşçakal$/
''selam'' bu kısımlar yakalanacak ''hoşçakal''
Düzenli İfadeleri PHP ile Kullanmak:
Gelelim bu faydalı işlemleri PHP üzerinde kullanmaya. Bunun için bir kaç faydalı fonksiyon ile tanışacağız.
İfadenin Eşleşip Eşleşmediğini Kontrol Etmek:
preg_match fonksiyonu ile yazdığımız ifadenin verdiğimiz içerikle eşleşmediğini kontrol edebiliyoruz. Örnekte girdinin geçerli bir saat formatı olup olmadığını kontrol edeceğiz.
Örnek Kullanımı:
PHP Kod:
Kod:
$pattern= '/^([01][0-9]|[2][0-3]):[0-5][0-9]:[0-5][0-9]$/';
$content = '23:15:59';
if(preg_match($pattern, $content))
{
echo 'Doğru bir saat girilmiş';
}
else
{
echo 'Yanlış bir saat formatı girilmiş';
}
Eğer ifade metin içerisinde eşleşirse true aksi halde false döner.
Yazdığımız ifadenin açıklamasını da merak ediyorsanız;
Öncelikle ^ ile metnin başını ifade ettik, yani tam olarak bizim istediğimiz gibi başlamalı. Sonunda da $ kullandık, bu sayede tam olarak bizim istediğimiz başlangıca ve sona sahip olan bir içeriği aradığımızı ifade ettik.
Sonrasında ([01][0-9]|[2][0-3]) 2 ifadeyi gruplandırdık. Çünkü saat ya 01 den 19′a kadar ya da 20 dan 23′e kadar olabilir. Eğer [0-9]{2} şeklinde 0 ile 9 arasında 2 sayı ile eşleş deseydik, 99 gibi 23′den büyük sayılara da eşleşirdi.
Yakalanan İçerikleri Almak:
Düzenli ifadelerde yakalamak ve ayırmak istediğimiz içeriklerin ifadelerini parantez içerisinde yazarız. Parantez içerisine yazılan ifadelere eşleşen içeriklere preg_match_all fonksiyonu sayesinde ulaşacağız. Bu fonksiyon tüm içeriği taramasını sağlayan “g” ayarını içerir, yani preg_match_all kullanırken “g” (global) ayarını yazmanıza gerek yok.
Teorik bilgi ve örneklerin haricinde biraz gerçek hayattaki kullanımlarına bakarak daha iyi kavrayabileceğimizi düşünüyorum. Bir sitenin kayak kodundan title etiketi arasında yer alan site başlığını yakalamak için şöyle bir ifade yazabiliriz.
Örnek kullanımı:
PHP Kod:
Kod:
$pattern = '/<title>(.+)<\/title>/i';
$content = file_get_contents('http://www.phpr.org');
preg_match_all($pattern, $content, $results);
print_r($results);
Ekran çıktısı şöyle olacaktır;
Örnek Çıktı:
Kod:
Kod:
Array
(
[0] => Array
(
[0] => <title>php serüvenleri - PHP dersleri, PHP örnekleri, PHP kodları</title>
)
[1] => Array
(
[0] => php serüvenleri - PHP dersleri, PHP örnekleri, PHP kodları
)
)
$results değişkenindeki dizinin ilk elemanı; girilen ifade ile eşleşen içeriklerin dizisini verir. Sonraki elemanları ise parantezler ile grupladığımız ifadelere eşleşen içeriklerin dizisini verir. Yani bizim asıl ihtiyacımız olan title etiketleri arasında parantez içerisine aldığımız karakterleri almak için 2. elemana bakacağız.
İkinci elemanda kendi içerisinde bir dizi, yani eğer birden fazla eşleşme olursa onları da sırayla verecektir.
Düzenli İfadeleri Kullanarak İçeriği Değiştirme:
Yine kullanışlı bir örnek ile açıklayalım. Girilen metin içerisine düz bir şekilde yazılan URL’leri HTML formatında link yapalım. Bunun için öncelikle bir URL’yi ifade edecek olan desen lazım. Ben internette hazır örneklerden birisini seçtim, dilerseniz siz de diğerlerine şuradaki adresten bakabilirsiniz. preg_replace fonksiyonu ile eşleşen ifadelerde yine parantez içinde grupladığımız ifadeleri istediğimiz şekilde değiştirebiliriz.
Örnek Kullanımı:
PHP Kod:
Kod:
// URL'leri yakalayan desen
$pattern = '(https?:\/\/(([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}\/?[^\b\s]+))';
$content = 'Diğer PHP serüvenlerine http://www.mybb.com.tr adresinden bakabilirsiniz';
$replace = '<a href="$0">$1</a>';
echo preg_replace($pattern, $replace, $content);
Ekranda düz yazı ile yazdığımız URL’nin link olmuş hali aşağıdaki gibi yazar;
Örnek Çıktı:
Kod:
Kod:
Diğer PHP serüvenlerine www.mybb.com.tr adresinden bakabilirsiniz.
Daha Fazlası:
İfade Gruplarını Yakalamamak:
Yukarıda özellikle yakalamak istediğimiz ifadeleri parantez içine almamız gerektiğini söylemiştim. Fakat her parantez içine aldığımızı yakalamak istemeyebiliriz. Bunun için parantezleri (?: ... ) şeklinde kullanabiliriz.
Böylece bu parantezin yakaladığı içerik sadece çalışırken kullanılır, sonuçta gösterilmez.
Örnek Kullanımı:
PHP Kod:
Kod:
/(\w+@\w+(?:\.\w+)+)/
E-posta adresini ifade eden desende iki grubumuz var, fakat içerideki grubu sonuçta almamıza gerek yok. İfadeyi çalıştırdığımızda sadece mail adreslerini veren bir dizimiz olacak.
İfade Gruplarını İsimlendirme:
Yukarıdaki örnekte gereksiz parantezleri almayıp elde ettiğimiz sonucu biraz daha düzene sokmuş olduk. Şimdi ise bu gruba isim vererek daha da düzeni sağlayabiliriz.
Grupları /(?<grupismi>ifade)/ şeklinde isimlendirebilirsiniz.
Örnek Kullanımı:
PHP Kod:
Kod:
$pattern = '/(?<email>\w+@\w+(?:\.\w+)+)/i';
$content = 'Bir kaç adres: info@mybb.com.tr, xpserkan@mybbgrup.com, info@myprobb.com';
preg_match_all($pattern, $content, $results);
print_r($results['email']);
Örnek Çıktı:
Kod:
Kod:
Array
(
[0] => info@mybb.com.tr
[1] => xpserkan@mybbgrup.com
[2] => info@myprobb.com
)
Böylece hiç dizi elemanlarının hangisi benim ihtiyacım olandı diye uğraşmadan direkt isim verdiğimiz grubun yakaladığı içeriklere ulaşabiliriz.
Hava Durumu:
Yine pratik bir örnek ile meteoroloji sitesinden İstanbul için günlük hava durumunu yakalayan bir desen hazırlayalım. Bu tür işlerin püf noktası aradığımız içeriği çevreleyen eşsiz desenleri görmek.
İstanbul için günlük hava durumunu veren sayfa;
Kod:
Kod:
http://www.mgm.gov.tr/tahmin/il-ve-ilceler.aspx?m=ISTANBUL
Sayfanın kaynağını açıp aradığımız sıcaklığın hangi HTML etiketleri arasında olduğuna bakıyoruz.
Örnek Kullanımı:
PHP Kod:
Kod:
$content = file_get_contents('http://www.mgm.gov.tr/tahmin/il-ve-ilceler.aspx?m=ISTANBUL');
// Derece
preg_match_all('/<em class="renkMin zemimeZ">(.+)C<\/em><\/td>/si', $content, $results);
// İlk eşleşeni alıyoruz
$degree = $results[1][0];
// Hava durumunun ikonu ve açıklaması
preg_match_all('/"([\wÇŞİĞÜÖöçşğüı ]+)" rowspan="2"><img src="\.\.([\w\/\.-]+)"/si', $content, $results);
$description = $results[1][0];
$image = 'http://www.mgm.gov.tr' . $results[2][0];
echo $degree . ' ' . $description;
echo '<img src="' . $image . '" />';
Bu şekilde ekranda hava durumunu görürüz.