Düzenli İfadeler (Regular Expressions)

Regular Expressions(Regex) Nedir ?

Regular Expressions (Düzenli İfadeler) kelimesinin kısaltması olan regex, e-posta adresi, tarih, telefon numarası gibi kullanıcı tarafından girilen ve belirli bir düzen içeren girdilerin kontrolünün sağlanması ve herhangi bir kod, metin içerisinde istenilen yazı veya kod parçasının aranıp bulunmasını, yönetilmesini sağlayan kendine ait söz dizimi olan bir yapıdır. Regular Expression syntax, Regex motorları arasında bazı farklılıklardan dolayı değişebilir ve farklı yorumlamalara sebep olabilir.

Kısaca Tarihçesi

1951 yılında matematikçi Stephen Cole Kleene, sonlu otomata ile tanımlanabilen ve düzenli ifadeler kullanılarak ifade edilebilen bir dil olan düzenli dil kavramını tanıttı. 1960'ların ortalarında Unix’in orijinal tasarımcılarından biri olan bilgisayar bilimi öncüsü Ken Thompson, Kleene’in notasyonunu kullanarak QED metin editöründe desen eşleştirme uyguladı. Bu gelişmeler sonucunda düzenli ifadeler (regex) ortaya çıkmıştır.

Neden Regex Kullanırız ?

Regex, metni eşleştirmek ve değiştirmek için kullanılabilecek güçlü bir araçtır. Belirli metin kalıplarını aramak ve değiştirmek için genellikle programlama dillerinde ve metin düzenleme yazılımlarında kullanılır. Düzenli ifadelerin bu kadar önemli olmasının ana nedenlerinden biri, metni çok esnek ve verimli bir şekilde aramanıza ve değiştirmenize izin vermesidir.

Kullanım Alanları Nelerdir ?

Yer değiştirme: Belirli parçaları değiştirir. Örnek olarak metin içerisindeki tüm büyük harfleri küçük harf ya da tüm küçük harfleri büyük harfe dönüştürebilirsiniz.

Doğrulama : Yazdığınız bir program olsun; bu programda büyük veya küçük harf, nokta veya rakam gibi kriterleri karşılayıp karşılamadığını kontrol edebilirsiniz.

Arama : Bir metin imzası içerisindeki tüm ögeleri aratabilirsiniz. Örneğin telefon numaraları ya da e-posta adresleri gibi.

Bilgi çıkarma: Bir metin dizisinden belirli bilgi parçalarını çıkarmak için düzenli ifadeleri kullanabilirsiniz. Örneğin, bir belgeden tüm tarihleri çıkarmak için düzenli ifadeleri kullanabilirsiniz.

Bunlarla birlikte veri tabanında metin araması yapmak, kullanıcı girişlerini doğrulamak, dosya isimlerinde toplu değişiklikler yapmak ve esnek ve karmaşık aramalar yapmak için Düzenli İfadeler'i kullanırız.

Regex Temelleri

  • \: Kaçış karakteridir. Regex motorumuzun özel karakterleri yorumlamaması için kullanılır.

  • |: Veya anlamındadır. Sağında ve solunda bulunan alternatif durumları seçer.

  • (): Gruplama amacıyla kullanılır. Öncelik sırası da sağlar.

  • (?:): Gruplama amacıyla kullanılır. Non-capturing grup olarak geçer. Parantez içerisine alınan ifadeyi bir grup olarak tanımlar, ancak eşleşen metni yakalamaz.

  • []: Karakter kümelerini belirtir. İçerisindeki karakterleri seçer.

  • [^]: Karakter kümesinin içerisinde olmayan karakterleri seçer.

  • -: Aralık belirtme amacıyla karakter kümelerinin içerisinde kullanılır.

  • .: Herhangi bir karakter ile eşleşir.

  • ^: Kendinden sonra gelen karakter veya grup ile satır başında eşleşir.

  • $: Kendinden önce gelen karakter veya grup ile satır sonunda eşleşir.

  • \b: Bir kelimenin sınırıyla eşleşir. Bir kelimenin başlangıcını ve sonunu belirtir.

  • \B: Bir kelimenin sınırlarıyla eşleşmez.

  • \A: Belirtilen karakter veya grup dizinin başındaysa eşleşir.

  • \Z: Belirtilen karakter veya grup dizinin sonundaysa eşleşir.

  • \w: Harf (a-z, A-Z), rakam (0–9) veya alt tire (_) karakterleri ile eşleşir.

  • \W: Harf, rakam veya alt tire olmayan karakterler ile eşleşir.

  • \d: Rakamlar (0-9) ile eşleşir.

  • \D: Rakam olmayan karakterler ile eşleşir.

  • \s: ' ', '\r', '\t', '\n' ve diğer Unicode boşluk karakterleri ile eşleşir.

  • \S: Boşluk karakterleri dışındaki karakterler ile eşleşir.

Miktar Belirleyici Karakterler

  • {}: Kendinden önce gelen karakter veya grup sayısıyla eşleşir.

  • ?: Kendinden önce gelen karakter veya grup 0 ya da 1 kez bulunuyorsa eşleşir.

  • *: Kendinden önce gelen karakter veya grup 0,1 ya da 1'den fazla kez bulunuyorsa eşleşir.

  • +: Kendinden önce gelen karakter veya grup 1 ya da 1'den fazla kez bulunuyorsa eşleşir.

Örnekler

  1. [abc] => a, b, c karakterleri seçilir. Selamlar abi karakter dizisindeki ['a','a','a','b'] karakterleri seçilir.

  2. [a-z] ASCII tablosundaki a ve z arasındaki karakterler seçilir. Yani [+-@] gibi bir ifade verseydik de ASCII tablosunda bu iki ifade arasında karakterler seçilirdi. ASCII tablosu aşağıda verilmiştir:

  1. [^abce] a, b, c, e karakterleri dışındaki karakterler seçilir. Merhaba karakter dizisi üzerinden ['M', 'r', 'h'] karakterleri seçilecektir.

  2. [1-30] ifadesi verilen herhangi bir karakter dizisi içinde 1, 2, 3 ve 0 karakterlerinin seçimiyle eşleşir.

  3. W..ld ifadesi Hello World! karakter dizisi içerisindeki World ifadesinin seçimiyle eşleşir.

  4. ^a ifadesi abc karakter dizisinin ['a'] karakter seçimi ile eşleşirken xabc karakter dizisi ile eşleşmez.

  5. on$ ifadesi Python karakter dizinin ['on'] karakter dizisi seçimi ile eşleşirken Sun karakter dizisi ile eşleşmez.

  6. [\w] ifadesi [a-zA-Z0-9_] ifadesi ile aynıdır. Bu karakterlerin hepsinin seçimiyle eşleşir.

  7. [\d] ifadesi 0471adc548 karakter dizisindeki ['0', '4', '1', '5', '4', '8'] karakterlerinin seçimi ile eşleşirken ['a', 'd', 'c'] karakterleriyle eşleşmez.

  8. ma*n ifadesi mn, man ve maan karakter dizilerinin seçimiyle eşleşirken main karakter dizisiyle eşleşmez.

  9. ma+n ifadesi man, maan ve maaan karakter dizilerinin seçimiyle eşleşirken mn karakter dizisiyle eşleşmez.

  10. ma?n ifadesi mn ve man karakter dizilerinin seçimiyle eşleşirken maan karakter dizisiyle eşleşmez.

  11. al{2} ifadesi a karakterinin ardından gelen l karakterinin 2 kere tekrar ettiği karakter dizilerinin seçimiyle eşleşir.

  12. al{2,4} ifadesi a karakterinin ardından gelen l karakterinin en az 2 veya en fazla 4 kere tekrar ettiği karakter dizilerinin seçimiyle eşleşir.

  13. [0-9]{5,} en az 5 basamaklı ve rakamlardan oluşan karakter dizileri ile eşleşir.

  14. a|b ifadesi a ya da b karakterlerini seçer. Aboubakar karakter dizisindeki ['a', 'b', 'b', 'a', 'a'] karakterlerinin seçimiyle eşleşir.

  15. \b(a|b|c)xz\b ifadesi axz, bxz ve cxz karakter dizilerinin seçimiyle eşleşirken dxz, axyz karakter dizileriyle eşleşmez.

  16. (a|b|c)xz ifadesi saxzb karakter dizisi içerisinden axz seçimiyle eşleşir.(Gruplamaların capturing özelliğine göre dönüş yapan metotlar için bu örnekte yine axz seçimiyle eşleşme olacak fakat bize gruplanmış değerlerin seçimi olan ['a'] karakteri metot tarafından döndürülecektir.)

  17. (.) ifadesi a.b karakter dizisindeki ['a', '.', 'b'] karakterlerinin seçimleriyle eşleşir.

  18. (a|b|\.)cd gruplamasında . karakteri özelliğini kaybedip regex motoru tarafından sadece ascii karakteri olarak yorumlanacak. Böylece sfs.cdls karakter dizisinin içerisinden .cd seçimiyle eşleşme sağlanır.

  19. \APython ifadesi Python ile Programlama dizesinin başındaki Python karakter dizisi seçimiyle eşleşir.

  20. Programlama\Z ifadesi Python ile Programlama karakter dizesinin sonundaki Programlama karakter dizisi seçimiyle eşleşir. Python ile Programlama Öğreniyoruz karakter dizisiyle herhangi bir eşleşme sağlamaz.

Popüler Regex Örnekleri

  • Bir kelimeyi eşleştirme: \b\w+\b

  • Bir e-posta adresi eşleştirme: \b\w+@[a-z]+.[a-z]{2,3}\b

  • Bir telefon numarasını eşleştirme: \b\d{3}-\d{3}-\d{4}\b

  • Bir IP adresiyle eşleştirme: \b\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\b

  • Bir tarih eşleştirme (mm/dd/yyyy): \b\d{2}/\d{2}/\d{4}\b

  • Bir zaman eşleştirme (HH:MM:SS): \b\d{2}:\d{2}:\d{2}\b

\b karakteri ile başlayıp biten ifadelerin amacı ifadeyi bununla sınırlamaktır. Örnek olarak \b\d{2}:\d{2}:\d{2}\b ifadesi HH:MM:SS şeklinde bir yapıyla eşleşecektir. Yani a23:50:12c karakter dizisi bizim için kabul edilemez. Bunu sağlayan ise \b karakterleri ile ifademizin sınırlanmasıdır. ifademiz ^\d{2}:\d{2}:\d{2}$ bu formatla da aynı sonucu verecektir.

Örnek olarak verilen ifadeler ekstra güvenlik gerektiren bir girdi kontrolünde kullanılacaksa yetersizdir. Örnek olarak \b\d{2}/\d{2}/\d{4}\b ifademizde tarih bilgileri sınırları aşılabilir.\b(0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/(190[6-9]|19[1-9]\d|20[01]\d|202[0-4])\b ifademizle birlikte ay sınırı 01-12 arasında, gün sınırı 01-31 arasında ve yıl sınırımız 1906 ila 2024 arasında olacağı garantilenmiştir.

Anlamlı Notlar

  • \b karakteri bir kelimenin başlangıcında veya sonunda olup olmadığına bakarken $ karakteri satır sonu karakteri ('\n') olmadan metnin sonuyla eşleşir.

  • $ ve \Z arasındaki fark satır sonu karakterine olan duyarlılıktır.

  • | karakteri sağında ve solunda bulunan alternatif durumların karmaşıklığına bakmaksızın bunları kullanır.

  • [a-z][A-Z][0-9] ifadesi ile [a-zA-Z0-9] ifadesi aynı anlama gelir.

  • ^$ bu iki karakterin birlikte kullanımı boş diziyle eşleşir.

  • .* bu iki karakterin birlikte kullanımı tüm karakter dizileriyle eşleşir.

  • [.] gibi karakter kümesi içerisinde verilen özel karakterler özelliğini kaybedip normal karakterlermiş gibi yorumlanır. Fakat aynı durum (.) ifadesi için geçerli değildir.

  • Python dilinle re kütüphanesinin içerdiği re.findall() metoduyla çalışırken bu metoda verilen r"A(nt|pple)" düzenli ifadesi ve Apple karakter dizisi bize parantez içerisinde eşleşen durumu getirecektir. Sebebi re.findall() metodunun Düzenli ifadede bir ya da daha fazla yakalama grubu içerdiğini görürse bunların bir listesini döndürmesidir. Bu durumların gerçekleşmesini istemiyorsak re.match(), re.finditer() metotları tercih edilebilir ya da (?:) ifadesiyle non-capturing grup kullanılabilir. Bahsedilen durumun Python kodu ve yorum satırı içerisindeki çıktıları aşağıda verilmiştir:

import re

sample="Apple"

result=re.findall(r"A(nt|pple)", sample)
print(result) # ['pple']

result=re.finditer(r"A(nt|pple)", sample)
for i in result: # Apple
	print(f"{i.group()}")

result=re.match(r"A(nt|pple)", sample)
print(result.group()) # Apple

Örnek Senaryoda Regex Kullanımı

Örnek bir senaryomuz üzerinden regex ifadesi oluşturalım ve inceleyelim: Senaryomuzda yazılımını yaptığımız bir websitesi tarama aracımız olduğunu varsayıyoruz. Daha sonra bu araç girdi olarak gelen websitesi URL' lerini düzenli ifademiz ile kontrol edecek. Bunun için oluşturduğumuz düzenli ifade aşağıdaki gibidir:

Görüldüğü üzere düzenli ifademizi bir URL yapısına uygun olacak şekilde yazdık. Şimdi parça parça açıklayalım:

  1. Scheme: ^https? şeklinde girildiğinden dolayı ilk 4 karakterin http seçimi zorunlu ve devamında gelen s? işareti ile birlikte s karakteri seçimi 0 ya da 1 kez bulunması şartıyla seçilebilir.

  2. Subdomain and Domain: [\w.-]+ şeklinde olan ifademiz \w karakterimiz ile birlikte a-z, A-Z, 0-9 arası karakterleri ve _ karakterini dahil eder; sonrasında gelen . ve - karakterleri ile bu karakterler de dahil olur ve seçim bu karakterler arasında gerçekleşir. [] kapanışından sonra gelen miktar belirleyici + karakteri ile 1 ya da 1'den fazla kez bu seçimin tekrarlanmasıyla eşleşme olur.

  3. TLD: \.[\w-]{2,3} bu kısımdaki seçim \. karakterleri ile birlikte . işareti ile seçim başlar ve sonrasında [\w-] seçimi takip eder. Bu takip eden seçimin ardından gelen miktar belirleyici {2,3} ifadesi takip eden seçimin uzunluğunun en az 2 veya en fazla 3 olma durumuyla eşleşir.

  4. Path and Query: (?:) başlangıcıyla non-capturing grup oluşturulur. Devamında gelen [] kapalı parantez ile seçim kümesi oluşturulur. Oluşturulan seçim kümesi sonuna gelen + işareti ile 1 ya da 1'den daha fazla kez seçim tekrarlanabilir olmuştur. () kapanışından sonra gelen * miktar belirliyici karakteri ile de non-capturing grubumuz 0, 1 ya da 1'den fazla kez tekrarlanabilecek bir seçim ile eşleşmesi sağlanır.

Örnek senaryoyu basitçe test edebileceğimiz Python kodları ve çıktısı aşağıda verilmiştir:

import re

url="http://merhaba.co/deneme?query=python&name=ali"

result=re.match(r"https?://[\w.-]+\.[\w-]{2,3}([\w.,@?^=%&:/~+#-]+)*", url)
#match() fonksiyonu kullanıldığı için (?:) non-capturing grup ve ^ dizi başlangıcı ifalerini kullanmadık.
print(result)

Çıktı:

Test Amaçlı Kullanılabilecek Araçlar
Bu yazı Dinçer Güner tarafından hazırlanmıştır.

Last updated