28 Aralık 2014 Pazar

PHP Regex Kullanımı


Regex'in temel kullanım amacı eşleştirme yapmak veya bir değer içerisinde başka bir değeri aratmaktır. En çok php ile bot yapımında karşınıza çıkacaktır. Email doğrulama, telefon numarası doğrulama veya kredi kartı bilgilerini doğrulama da büyük iş görür.

En Basit Haliyle Regex

Şimdi basit bir string oluşturup o string içerisinde aradığımız karakter var mı yok mu aratalım:

$string = 'phpdeveloper';
echo preg_match("/dev/", $string);

string isimli bir değişken oluşturduk. Değer olarak 'phpdeveloper' verdik. Bu değer içerisinde preg_match metodunu kullanarak 'dev' karakterleri var mı yok mu diye sorgulattık. Bu işlemi echo ettirdiğimiz zaman sonuç 1 çıkacaktır. 1 'dev' karakterleri bulundu anlamına gelir. Sonuç bulamazsa 0 değerini verir...

String Değerinin Başlangıcını Eşleştirmek

$string = 'phpdeveloper';
echo preg_match("/^php/", $string);

String değerinin başlangıcını eşleştirmek için ^ karakterini kullanıyoruz. Yukarıda ki kodu çalıştırdığımızda sonuç 1 olacaktır.

String Değerinin Sonunu Eşleştirmek

$string = 'phpdeveloper';
echo preg_match("/per\$/", $string);

String değerinin başlangıcını eşleştirmek için $ karakterini kullanıyoruz.
Burada dikkat etmeniz gereken yer \ işaretini $ den önce kullanmak zorundasınız.
Yukarıda ki kodu çalıştırdığımızda sonuç 1 olacaktır.
Unutmadan $ yerine z işareti koyarsanız aynı işi görecektir.



Büyük Küçük Harfe Karşı Duyarlı

Yukarıda yazdığımız kodlar büyük küçük harfe karşı duyarlıdır. Yani 'Php' olarak aratırsanız sonuç 0 çıkar. Regex büyük küçük harf uyumunu kaldırmak için sonuna i eklememiz gerekir.

$string = 'phpdeveloper';
echo preg_match("/^Php/", $string);

Sonuç 0 çıkar.

$string = 'phpdeveloper';
echo preg_match("/^Php/i", $string);

Sonuç 1 çıkar.

Meta Karakterler Ve Meta Karakterleri Kaçırmak

Meta karakterlerden kastım az önce kullandığım z ^ $ gibi işaretlerdir. Bu meta karakterlerden başka şu karakterlerde bulunmakta:
. * ? [ ] { } | ( ) +

Yazının devamında bu meta karakterler için birer regex örnekleri vereceğim. Örnekelere geçmeden önce meta karakterlerin nasıl normal karakterden ayırt edilidğini görmemiz lazım.

$string = '1+1=2';
echo preg_match("/^1+1/i", $string);

Bu örneğin sonucu 0 dır. Çünkü + işaretini meta karakter olarak algılıyor sistem. Yani '1+1' olarak görmüyor.

$string = '1+1=2';
echo preg_match("/1\+1/i", $string);

Bu örneğin sonucu 1 dir. + işaretinin öncesine \ yani backslash işareti koyarak +'nın meta karakter olmadığını normal + işareti olduğunu gösteririz.

Şimdi sırasıyla regular expression ile meta karakterlerin kullanımına bakalım:

Köşeli Parantez Bracket İle Regex Kullanımı

$string = 'bir';
echo preg_match("/b[lki]r/", $string);

Bu örnekte köşeli parantezin içinde birden fazla karakter var. Bu karakter topluluğu Characket Class yani karakter sınıfı olarak adlandırılır. bir değerinin içinde l, k ve i değeri var mı yok mu diye arattığımızda köşeli parantezleri bu şekilde kullanınırız. Verdiğimiz karakter sınıfında eğer i harfi var ise  sonuç 1 yok ise 0 olacaktır.

$string = 'bir';
echo preg_match("/b[asd]r/", $string);

Karakter sınıfı asd ve i harfi yok. Sonuç 0

$string = 'bir';
echo preg_match("/b[+aasdf$]r/", $string);

Bu örnekte karakter sınıfında + ve $ işaretlerini kullandık fakat backslah \ işaretini kullanmadık. Bunun sebebi karakter sınıfı içerisinde yer alan karakterler meta karakter sayılmaz. Tabi bazı istisnai durumlar yok değil. Mesela köşeli parantez içerisinde ^ (caret) işareti kullanırsak karakter sınıfında yer alan karakterler hariç diye aratır.

$string = 'abcefghijklmnopqrstuvwxyz0123456789';

preg_match_all("/[^b]/", $string, $matches);

foreach($matches[0] as $value)
{
echo $value;
}

Bu kodun çıktısı:
acefghijklmnopqrstuvwxyz0123456789

şeklindedir. Dikkat ederseniz b harfi hariç diğer bütün karakterleri aldı.

Bu kodda preg_match yerine preg_match_all kullandık. preg_match bulduğu ilk değeri dikkati alır ve işlemi sonlandırırdı. preg_match_all ise tüm değerleri baştan sona dikkate alır.

Bu işi biraz daha karmaşık yapalım. Örneğin 0 ile 9 arasında ki sayılar hariç diğer karakterleri getirelim:

$string = 'abcefghijklmnopqrstuvwxyz0123456789';

preg_match_all("/[^0-9]/", $string, $matches);

foreach($matches[0] as $value)
{
echo $value;
}

Bu kodun çıktısı:
abcefghijklmnopqrstuvwxyz

0-9 sıfır ile dokuz arasında yer alan bütün sayılar. ^0-9 ise sıfır ve dokuz arasında yer alan hiç bir sayı.


Meta Karakterleri Anlatmaya NOKTA ile Devam Edelim

Nokta . meta karakterinin anlamı her hangi bir karakter anlamına gelir.

$string = 'php developer';

echo preg_match("/p.p/", $string);

 p ve p karakterleri arasında her hangi bir karakter var mı diye kontrol ediyoruz. Bu kodun çıktısı 1 dir.

Asteriks *

Asteriks bizim deyişimizle yıldızın kullanım amacı bir karakterden önce belirtilen bir karakterin olup olmadığını belirler

$string = 'php'; 

echo preg_match("/ph*p/", $string);

Bu kodun çıktısı 1 dir. Çünkü p karakterinden önce belirtilen karakter var. Peki ya kodumuzu şu şekilde olursa:

$string = 'pp'; 

echo preg_match("/pz*p/", $string);

Burda pp içerisinde pz'yi aratıyoruz. Sonucun 0 olarak çıkması gerektiğini düşünmeniz gayet normal fakat sonuç  1 olarak çıkar bunun sebebi. Asteriksten önce pz yazında p karakterini dikkate almasıdır.

İşte Tam Burda Devreye Artı + Meta Karakteri Devreye Giriyor

Bir önceki kodu + meta karakteri ile yaparsak:

$string = 'pp'; 

echo preg_match("/pz+p/", $string);

Bu kodun çıktısı beklendiği gibi 0'dır. Bu şekilde pp karakterleri içerisinde pz karkaterlerini aratmış olduk.

Soru İşareti ? Meta Karakteriyle Dizinin Devamını Aramak

$string = 'phpdeveloper';

echo preg_match("/php?developer/", $string);

Soru işaretinden sonra gelen veriyi bulduğu için sonuç 1 olacaktır.

Kıvrımlı Parantez { } Meta Karakteri

Adınız yanlış söylemiş olabilirim. İngilizcesiyle curly braces meta karakteri belki biraz kafa karıştırıcı olabilir ama emin olun çok işinize yarayacak. Bir karakter sınıfı içerisinde [] değerlerin kaç kere döndüğünü gösterelim. Bu cümlenin tek başına bi anlam ifade etmediğinin farkındayım o yüzden hemen bir örnek vermek iyi olacak:

$string = 'php1234';

echo preg_match("/php[0-9]{3}/", $string);

Karakter sınıfında 0 dan 9 a kadar olan sayıları seçtik. Bu karakter sınıfı php den sonra gelen 1234 karakterleri içerinde 0 dan 9 a kadar sayı olup olmadığını kontrol eder. Curly braces içerisinde ki {3} ün anlamı ise karakter sınıfında ki değerlerin kaç kere eşleştiğini gösterir. Karakter sınıfında 0-9 arasında ki sayılar 4 kere eşleşiyor. Biz 3 kere eşleştiğini söyledik. Sonuç 4 ten küçük olduğu için kodun çıktısı 1 olacaktır. Eğer curly braces {4} olsaydı sonuç yine 1 olacaktı. Fakat {5} yaparsak bu sefer değerlerin en beş kere eşleştiğini belirtmiş oluruz. Bu yüzden sonuç 0 olur.

VEYA Operatörü | ile İşlem Yapmak

$string = "php developer";

echo preg_match("/(pzp|prp|php)/", $string);

php developer kelimesinde pzp veya prp veya php kelimesi var mı  diye sorduk. Çıkan sonuç 1 olacaktır.

String Değerinin Sayı İle başlayıp Başlamadığını Anlamak

Regular expression da kullanılan bazı özel dizinler (special sequences) vardır. Bunlar daha az kodla daha fazla iş yapmamıza örnek sağlar.

Bu özel dizinler :

\d - her hangi bir sayı ile eşleştir - diğer şekli [0-9]
\D - sayısal olmayan değerlerle eşleştir - diğer şekli [^0-9]
\s - white space işe eşleştir - diğer şekli [ \t\n\r\f\v]
\S - white space olmayan karakterlerle eşleştir - diğer şekli [^ \t\n\r\f\v]
\w - Alfa numerik karakterlerle eşleştir - diğer şekli [a-zA-Z0-9_]
\W - Alfa numerik olmayan karakterlerle eşleştir - diğer şekli  [^a-zA-Z0-9_]


Bu özel dizinlerle işimizi daha kolay yollarla halledebileceğiz. Şimdi string değerinin sayı ile başlayıp başlamadığını bulmaya çalışabiliriz

$string = '2 php developers';

echo preg_match("/^\d/", $string);

Bu kodun çıktısı 1 dir.



Kelimeyi Harfi Harfine Almak

Regex içerisinde bazı niteleyiciler vardır. Daha önce yazmış olduğum büyük küçük harf uyumunu insensitive yapan i niteleyicisi gibi. Diğer bir niteliyici ise boundary (sınır) kelimesinin ilk harfi olan b dir. Aratmak istediğiniz kelimeyi iki \b arasında yazarak kesin sonuç elde edebilirsiniz.

$string = 'php developer';
echo preg_match ("/\bloper\b/i", $string);

Bu kodun çıktısı 0'dır. $string içerisinde loper diye bir şey olabilir ama biz kelimeyi tam olarak arattığımızdan dolayı sonuç 0 dır.

$string = 'php developer';
echo preg_match ("/\bdeveloper\b/i", $string);

developer kelimesi ile harfi harfine eşleştiği için bu kodun çıktısı 1 olacaktır.

Eğer $string içerisinde bir grup harften oluşan eşleşme istersek B niteliyicisini kullanmamız gerekmektedir.

$string = 'php developer';
echo preg_match ("/\Bloper\b/i", $string);

preg_replace() İle İşlem Yapmak

preg_replace() bir kelimeyi başka bir kelime ile değiştirmeye yarar:

$string = 'php developer';
$string = preg_replace("/php/", 'java', $string);

Bu kodun çıktısı 'java developer' olacaktır.

Bir Karakterin Sonrasını Aratmak

$string = 'php developer herkes olabilir';
echo preg_match("/(?<=her)kes/i", $string);

her kelimesinden hemen sonra kes kelimesi geldiği için sonuç 1 çıkar. herkes kelimesi ayrı yani her kes şeklinde yazalım.

$string = 'php developer her kes olabilir';
echo preg_match("/(?<=her)kes/i", $string);

Bu kodun çıktısı 0 dır. her den sonra kes gelebilir fakat arada boşluk olduğu için sonuç 0 olur. Bunun çözümü ise ?<= yerine ?!= yazmaktır:

$string = 'php developer her kes olabilir';
echo preg_match("/(?!=her)kes/i", $string);

Bu kodun çıktısı 1 dir.

Bir Karakterin Öncesini Aratmak

$string = 'php developer herkes olabilir';
echo preg_match("/her+(?=kes)/i", $string);

kes kelimesinden hemen önce her kelimesi geldiği için sonuç 1 çıkar. Peki ya herkes kelimesi ayrı yani her kes şeklinde yazılsaydı sonuç nasıl olurdu.

$string = 'php developer her kes olabilir';
echo preg_match("/her+(?=kes)/i", $string);

Bu kodun çıktısı 0 dır. kes den önce her gelebilir fakat arada boşluk olduğu için sonuç 0 olur. Bunun çözümü ise ?= yerine ?! yazmaktır:

$string = 'php developer her kes olabilir';
echo preg_match("/her+(?!kes)/i", $string);

Çıkan sonuç 1 olacaktır.



Niteleyiciler - İfadeler - Sınırlayıcılar (Modifiers - Assertions - Delimiters)

Özel Dizinler (Special Sequence)

\d - her hangi bir sayı ile eşleştir - diğer şekli [0-9]
\D - sayısal olmayan değerlerle eşleştir - diğer şekli [^0-9]
\s - white space işe eşleştir - diğer şekli [ \t\n\r\f\v]
\S - white space olmayan karakterlerle eşleştir - diğer şekli [^ \t\n\r\f\v]
\w - Alfa numerik karakterlerle eşleştir - diğer şekli [a-zA-Z0-9_]
\W - Alfa numerik olmayan karakterlerle eşleştir - diğer şekli  [^a-zA-Z0-9_]

Meta Karakterler

^ - cümlenin başlangıcı
$ - cümlenin bitişi
[ - karakter klası açılış işareti
] - karakter klası kapanış işareti
| - veya operatörü, Örn: a|b = a veya b
( ) - Alt pattern
\ - karakteri kaçır

Niteleyiciler (Quantifiers)

n* - n karakterinden 0 veya daha fazla
n+ - n karakterinden 1 veya daha fazla
n? - n karakterinden 0 veya 1 kez olması
{n} - n sayısı kadar
{n,} - en az n sayısı kadar
{n,m} - n ve m (dahil) sayısı arasında

Kalıp Niteleyicileri (Pattern Modifiers)

i - Büyük küçük harfa duyarsız
m - Çoklu satır
s - \n yani yeni satır kodunu görmesini sağlar
x - string içinde kullanılan yorumları
e - sadece preg_replace() metodu ile çalışır
U - regex kalıbını sınırlandırır
u - regex kalıbını Ut-8 olarak ele alır

İfadeler (Assertions)
\b - Kelimeyi bütün olarak ele alır
\B - Kelimenin içinde ki harfleri ele alır
\A - cümlenin başlangıcı
\Z - Yeni satırda \n cümlenin bitişi
\z - Cümlenin bitişi
\G - Cümlenin ilk eşleşen hali

Diğer İfadeler
(?=) - Bir karakterin öncesini aratmak (pozitif)
(?!) - Bir karakterin öncesinde olmayanı aratmak (negatif)
(?<=) - Bir karakterin sonrasını aratmak (pozitif)
(?<!) - Bir karakterin sonrasını aratmak (negatif)
(?>) - Sadece alt kalıpları aratır
(?(x)) - Koşullu alt kalıplar
(?(3)foo|fu)bar - Eğer 3. alt kalıp eşleşirse foo ile eşleşir





11 yorum:

  1. Bu konuda nette bulduğum en iyi anlatım diyebilirim..çok çok teşekkürler..

    YanıtlaSil
  2. Merhabalar preg_match ile veri tabanındaki makalenin içindeki bir resmin linkini nasıl alabilirim

    YanıtlaSil
    Yanıtlar
    1. merhaba, denemedim ama bu kod işini görür:
      preg_match('/< *img[^>]*src *= *["\']?([^"\']*)/i', $row->introtext, $matches);

      kaynak: http://stackoverflow.com/questions/2180255/matching-src-attribute-of-img-tag-using-preg-match

      Sil
    2. bu olmadı ya hata veriyor

      Sil
    3. kodu görmeden regular expression konusunda bu kadar yardımcı olabiliyorum :(

      Sil
  3. text = $row['makale_metin'];
    preg_match('/src="(?P.*\.(jpeg|png|jpg))"/', $text, $matches);
    echo $matches['image'];?>

    bu şekilde yaptım oldu ama metin içindeki bütün resimleri alıyor ben sadece ilkini almak istiyorum

    YanıtlaSil
  4. Teşekür ederim. Allah razı olsun.

    YanıtlaSil