PHP'de Düzenli İfade Desenlerinin (Pattern) Yazımı

PHP'de düzenli ifadelerin kurallarını, kullanımını ve düzenli ifadeler için kullanılan fonksiyonları buradaki yazımda anlatmıştım. Bu yazımda düzenli ifadelerde kullanabileceğiniz desenleri (pattern) oluşturmayı örneklendirerek anlatmaya çalışacağım.

Öncelikle basit bir şekilde bir metin içerisinde belli bir sözcük öbeğini aradığınızı varsayalım. Bunun için her hangi bir desen yazmanıza gerek yoktur.

$str = "Regex kullanarak kodlama yapmak çok güzeldir.";
$pattern = "/Güzel/iu";

if(preg_match($pattern, $str)){
echo "Vardır.";
}else{
echo "Yoktur!";
}

Yukarıdaki örnekte $str değişkeni içerisinde "Güzel" ifadesinin varlığını kontrol ettirdik. Yukarıdaki kod çalıştırıldığında ekrana Vardır. yazacaktır.

Not : Buradaki yazıdan hatırlayacağınız gibi desenin sonunda kullandığımız i küçük-büyük harf duyarsız olacağını belirttik. u ile de desenin UTF-8 karakterlerini doğru şekilde algılanmasını sağlamış olduk.

Bir desen oluştururken kullanabileceğiniz belli yazım şekilleri ve bunların ifade ettiği belli karakterler vardır.

İFADE | AÇIKLAMA
^ | Dizenin başlangıcını ifade eder.
$ | Dizenin sonunu ifade eder.
\b | Desene uygun yapıyı dizenin başında ve sonunda aramak için kullanılır.
\B | Desene uygun yapıyı dizenin içerisinde arama yapmak için kullanılır.
?= | Dize içerisindeki belirtilen bir referans değerin önünde desen ile eşleşebilecek değerleri aramak için kullanılır.
?! | Dize içerisindeki belirtilen bir referans değer ile takip edilmeyen değerleri desen ile eşleşebilecek değerleri aramak için kullanılır.
{x} | Kendisinden önce yazılmış ifadenin en az x defa tekrar etmesi gerektiğini belirtir.
{x,} | Kendisinden önce yazılmış ifadenin en az x defa ya da daha fazla kez tekrarlanması gerektiğini belirtir.
{x,y} | Kendisinden önce yazılmış ifadenin en az x defa, en fazla y defa tekrarlanması gerektiğini belirtir.
+ | Kendisinden önce yazılmış ifadenin 1 ve ya daha fazla kez tekrarlanmış olması gerektiğini belirtir.
* | Kendisinden önce yazılmış ifadenin 0 ve ya daha fazla kez tekrarlanmış olması gerektiğini belirtir.
? | Kendisinden önce yazılmış ifadenin 0 ve ya 1 defa tekrarlanmış olması gerektiğini belirtir.
() | Parantezler içerisindeki desen yapısını gruplanmak için kullanılır.
(x|y) | VEYA. Dik çizgi, desen grubu içerisinde VEYA görevi görür. x VEYA y desenlerinden herhangi biri eşleşmelidir.
(?:) | Desenler içerisinde alt gruplar oluşmak için kullanılır.
\ | Ters eğik çizgi, kendisinden sonra gelecek karakterin özel bir karakter yani işlevi olan bir karakter olarak algılanmaması için kullanılır.
[abc] | Köşeli parantezler, içerisindeki karakterlerin herhangi bir ya da daha fazlasının eşleşmesinin kabul edileceğini belirtir.

[a-z]

Köşeli parantezler içerisinde tire; karakter aralığı belirlemek için kullanılır.

[a-z] : "a" ve "z" karakterleri de dahil, arasında kalan Latin alfabesindeki tüm harflerin küçük karakterleri ifade eder.
[A-Z] : "A" ve "Z" karakterleri de dahil, arasında kalan Latin alfabesindeki tüm harflerin büyük karakterlerini ifade eder.
[0-9] : "0" ve "9" dahil, ikisi arasındaki rakamı ifade eder.

[^abc]

Şapka sembolü kendisinden sonra tanımlanan karakterli hariç tutulacağı anlamına gelir.

[^abc] : Dize içerisinde a, b ve c karakterlerini olmaması gerektiğini ifade eder.

[^a-z]

Belli bir karakter aralığındaki karakterlerin hariç tutulacağı tanımlamak için kullanılır.

[^a-f] : Dize içerisinde a, b, c, d, e ve f karakterlerinin olmaması gerektiğini ifade eder.

. | Satır başı hariç herhangi bir karakteri ifade eder.
\w | Tüm alfanumerik karakterleri ve alt çizgi "_" karakterini ifade eder.
\W | Alt çizgi "_" ve alfanumerik karakterler haricindeki karakterleri ifade eder.
\d | Rakamları ifade eder.
\D | Rakam olmayan karakterleri ifade eder.
\s | Boşluk, TAB, satır başı gibi bir sembol ile temsil edilmeyen (gösterilmeyen) karakterleri temsil eder.
\S | Boşluk, TAB, satır başı gibi bir sembol ile temsil edilmeyen (gösterilmeyen) karakterler haricindeki karakterleri temsil eder.

Yukarıdaki tablodan yola çıkarak çeşitli desenler (patterns) yazmak mümkündür. Şimdi gelin çeşitli örneklerle farklı desenleri nasıl yazabileceğimize bir bakalım.

Örnek 1

Bir dize içerisindeki sayıları yakalamak istiyorsanız.

$veri = "Ahmet eve gelirken 3 ekmek, 12 tane muz getirmişti.";
$pattern = "/[0-9]+/";

if(preg_match_all($pattern, $veri, $out)){
print_r($out[0]);
}else{
echo "Dize içerisinde herhangi bir rakam bulunamadı.";
}

ya da

Yukarıdaki ile aynı işi yapacak olan şöyle bir desen yazabilirdim;

$veri = "Ahmet eve gelirken 3 ekmek, 12 tane muz getirmişti.";
$pattern = "/(\d+)/";

if(preg_match_all($pattern, $veri, $out)){
print_r($out[0]);
}else{
echo "Dize içerisinde herhangi bir rakam bulunamadı.";
}

Her iki örneğinde çıktısı :

Array
(
[0] => 3
[1] => 12
)

şeklindedir.

Örnek 2

Belli bir kalıba sahip dize içerisindeki belli bir bölümü yakalamak istersek;

$str = "Hello, My name is Muhammet.";
$pattern = "/my name is ([a-zA-Z]+)/i";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize içerisinde istenilen desen bulunamadı.";
}

ya da

$str = "Hello, My name is Muhammet.";
$pattern = "/my name is (\w+)/i";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize içerisinde istenilen desen bulunamadı.";
}

Her iki örneğinde çıktısı:

Array
(
[0] => My name is Muhammet
[1] => Muhammet
)

şeklindedir.

Bu örnekte bir ş, ö, ç gibi Türkçe karakterler olmadığı için eşleşme sağlandı. Ancak bir Türkçe karakter bulunsaydı eşleşme sağlıklı çalışmayacaktı.

Türkçe karakterleri kabul etmek istiyorsanız; bunları desene ayrıca belirtmelisiniz.

Türkçe Karakterlerin Desene Tanımlanması :

$str = "My surname Şafak.";
$pattern = "/my surname ([a-zA-ZÇŞĞÜÖİçşğüöı]+)/iu";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize içerisinde istenilen desen bulunamadı.";
}

Çıktısı :

Array
(
[0] => My surname Şafak
[1] => Şafak
)

Görebileceğiniz gibi Türkçe karakterleri tek tek belirttim ve karakterleri doğru şekilde verebilmesi için u ayarını desene uyguladım.

Örnek 3 : Tarih Formatına Uygun Desen Yazmak

Biraz daha karmaşık yapılarak geçelim. Bir dize içerisinde DD/MM/YYYY biçimindeki tarihleri almak için bir desen yazalım. İlk başta biraz karmaşık gelebileceği için bu işlem için yazacağım deseni açıklama gereği duydum. Hem böylece bir düzenli ifade desenine baktığınızda okuyabilir olmanızı umuyorum.

((0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([0-9]{4}))

Yukarıdaki deseni inceleyelim;

(0[1-9]|[1-2][0-9]|3[0-1]) : İlk karakteri 0 ise ikinci karakteri 1 ila 9 arasında bir değer olmalıdır VEYA ilk karakteri 1 ya da 2 ise ikinci karakteri 0 ile 9 arasında olmalıdır VEYA ilk karakteri 3 ise ikinci karakter 0 ya da 1 olmalıdır. Böylece 01 ile 31 arasında 2 basamaklı bir sayı aradığımızı belirtmiş olduk.

(0[1-9]|1[0-2]) : İlk karakteri 0 ise ikinci karakter 1 ile 9 arasında bir değer olmalıdır VEYA ilk karakteri 1 ise ikinci karakter 0 ila 2 arasında bir değer olmalıdır. Böylece 01 ile 12 arasında 2 basamaklı bir sayı aradığımızı belirtmiş olduk.

([0-9]{4}) : 0 ila 9 arasında 4 basamaklı bir sayı olmalıdır. Böylece 0000 ile 9999 arasında 4 basamaklı bir sayı aradığımızı belirtmiş olduk.

Desenler arasında kullandığımız "/" sembolü normal şartlarda düzenli ifadeler için özel bir anlama sahip olduğundan önüne ters eğik çizgi ekledim. Böylece bu sembolün normal bir karakter olarak algılanmasını sağladım.

Sonuç olarak bu desen; 01/01/0000 ile 31/12/9999 arasındaki herhangi bir tarih ile eşleşme sağlayacaktır.

$str = "Bugünün tarihi 28/09/2021 günlerden Salı. Yarın 29/09/2021 günlerden Çarşamba.";
$pattern = "/((0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([0-9]{4}))/";

if(preg_match_all($pattern, $str, $out)){
print_r($out[0]);
}else{
echo "Dize içerisinde uygun formatta tarih bulunamadı.";
}

Çıktısı :

Array
(
[0] => 28/09/2021
[1] => 29/09/2021
)

Örnek 4 : Saat Formatına Uygun Desen Yazmak

Bir verinin tam olarak istediğimiz şeyi istediğimiz şekilde vermesini istiyorsak; ^ ve $ sembollerini kullanarak başlangıç ve bitişi desene bildirmeliyiz.

Örneğin Saat:Dakika:Saniye (HH:II:SS) formatında bir veri bekliyoruz ve buna uygun bir desen yazmamız gerekiyor. Öyleyse;

$str = "23:09:42";
$pattern = "/^([0-1][1-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize istenilen desen ile uyumlu değildir.";
}

Çıktısı :

Array
(
[0] => 23:09:42
[1] => 23
[2] => 09
[3] => 42
)

şeklindedir.

Bu deseninin başında ^ kullanarak tam olarak bizim belirttiğimiz şekilde başlaması gerektiğini ve sonunda $ kullanarak tam olarak bizim belirttiğimiz şekilde bitmesi gerektiğini ifade etmiş olduk.

Örnek 5 : Dize İçerisindeki Mail Adreslerini Alalım!

Bir dize içerisindeki mail adreslerini almak istediğimizi düşünelim. Öyleyse yazmamız gereken desen şu şekildedir;

$str = "Ahmetin mail adresi ahmet@domain.com Mehmetin mail adresi mehmett@domain.com";
$pattern = "/[a-z0-9\-\.]+@[a-z0-9\-\.]+/i";

if(preg_match_all($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize istenilen desen ile uyumlu değildir.";
}

Çıktısı:

Array
(
[0] => Array
(
[0] => ahmet@domain.com
[1] => mehmett@domain.com
)

)

şeklindedir.

Örnek 6 : Bir Mail Adresinin Kullandığı Domaini Alma

Bir mail adresindeki domain bilgisini öğrenmemiz gerektiğini düşünelim. Öyleyse yazmamız gereken desen şu şekildedir;

$str = "info@muhammetsafak.com.tr";
$pattern = "/^([a-z0-9\-\.]+)@([a-z0-9\-\.]+)$/i";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize istenilen desen ile uyumlu değildir.";
}

Çıktısı:

Array
(
[0] => info@muhammetsafak.com.tr
[1] => info
[2] => muhammetsafak.com.tr
)

şeklindedir.

Örnek 7 : HTML Dökümanı İçinde Title Metasını Almak

$str = ' PHPde Regex Pattern Oluşturma Link 1';

$pattern = "/<title.*>(.+)<\/title>/i";

if(preg_match($pattern, $str, $out)){
print_r($out);
}else{
echo "Dize istenilen desen ile uyumlu değildir.";
}

Çıktısı:

Array
(
[0] => PHPde Regex Pattern Oluşturma
[1] => PHPde Regex Pattern Oluşturma
)

şeklindedir.

Sonsuz sayıda örnek verilebilir ancak bu kadar örneğin öğrenmek için yeterli olduğunu düşünüyorum. Anlamadığınız bir yer olursa yorumlardan sorabilirsiniz.