Regular Expression Tam Olarak Ne?
Regular Expression’lar (kısaca Regex’ler), başka String’ler üzerinde bazı yaygın işlemleri gerçekleştirmek için DSL (domain-specific language, alana özgü dil) olarak çalışan String’lerdir. DSL’i “bir programlama dili içinde programlama dili” olarak da tanımlayabiliriz.
Regex’ler söz konusu olduğunda, dış programlama dili String tipini destekleyen herhangi bir programlama dili olabilir, yeter ki Regex desteği olsun. Neredeyse tüm popüler programlama dilleri Regex’leri destekler, bu da Regex bilmeyi çok değerli kılar. Regex’lerin iç dili sadece String’den oluşur ve bazı karakterlerin özel bir anlamı vardır.
Örneğin ".*@.*\\.com" String’inde . “herhangi bir karakter”, * “önceki şeyden herhangi bir sayıda” anlamına gelir, birlikte .* “herhangi bir sayıda herhangi bir karakter” demektir. Sonra özel olmayan bir @ karakteri var, ardından yine .* geliyor, sonra \\ var ki bu “sonraki karakteri özel anlam olmadan normal karakter olarak yorumla” demek, yani \\. birlikte “herhangi bir karakter” özel anlamı olmadan normal bir . karakteri olarak okunur. Son olarak com var, bunlar özel bir anlamı olmayan karakter dizisi. Toplamda bu Regex, .com ile biten ve içinde bir yerde @ bulunan herhangi bir e-posta adresi için basit bir eşleştiricidir.
“Regular Expression DSL’i” ile Ne Yapabilirim?
ℹ️ Ruby kuruluysa (Mac’lerde önceden yüklü gelir), terminalde
irbyazarak interaktif Ruby kabuğu başlatabilir ve aşağıdaki örnekleri deneyebilirsin.
Herhangi bir Regex string’inin kullanılabileceği üç ana fonksiyon vardır:
matches: Bir Regex ve başka bir String verildiğinde, bu fonksiyon verilen String’in Regex’le “eşleşip eşleşmediğini” kontrol eder. Yani verilen String’de Regex’le eşleşen “herhangi bir” kısım varsatrue, yoksafalsedöner. Örneğin Ruby’de (matchesfonksiyonumatch?olarak adlandırılır —?fonksiyon adının parçasıdır):
/.*@.*\\.com/.match?('[email protected]') # => false /.*@.*\\.com/.match?('[email protected]') # => truecaptures: Bir Regex ve başka bir String verildiğinde, bu fonksiyon verilen metinden Regex’in işaretlenmiş kısımlarıyla eşleşen alt string’leri okuyabilir. Regex’teki kısımlar(ve)ile işaretlenebilir. Bunlara “yakalama grupları” (capture groups) denir. Örneğin Ruby’de (capturesfonksiyonunaMatchnesnesi üzerinden erişilir):
/(.*)@(.*)\\.com/.match('[email protected]').captures # => ["queenie.goldstein", "ilvermorny"]replace: Bir Regex ve bir Şablon String verildiğinde, bu fonksiyon eşleşmeleri otomatik olarak verilen String ile değiştirebilir; yakalama gruplarına bile$1,$2veya bazı dillerde\\1,\\2gibi referanslar verilebilir. Örneğin Ruby’de (replacefonksiyonugsubolarak adlandırılır):
'[email protected]'.gsub(/(.*)@(.*)\\.com/, '\\1@\\2.org') # => "[email protected]"“Regular Expression DSL’i” Nasıl Görünür?
Harika örneklerle dolu birçok faydalı “kopya kağıdı” (cheat sheet) var:
Genel olarak anlaşılması gereken 5 farklı DSL bileşeni türü vardır:
1. Karakter/Grup Değiştiricileri (örn. *, +, {,}, ?)
Regex’lerin varsayılan “yapı taşı” karakterlerdir. Her karakterden sonra, önceki karakterin kaç kez eşleşeceğini belirten bir değiştirici yazabilirsin. Kullanılabilir değiştiriciler şunlardır:
**0 veya 1 kez: **
? (örnek: a?b?c? şunların hepsini eşleştirir: a, ab, abc, bc, c)
**Tam olarak 1 kez: **
Değiştirici yok (varsayılan)
**0 ila ♾️ kez: **
* (örnek: a*bc şunları eşleştirir: bc, abc, aaabc)
1 ila ♾️ kez:
+ (örnek: a+bc şunları eşleştirir: abc, aaabc ama bc’yi eşleştirmez)
Tam olarak X kez:
{X} (örnek: a{3}bc sadece aaabc’yi eşleştirir, aabc veya aaaabc’yi değil)
X ila Y kez:
{X,Y} (örnek: a{2,5}bc aaaaabc’yi eşleştirir ama abc’yi eşleştirmez)
X ila ♾️ kez:
{X,} (örnek: a{2,}bc aaaaaaaabc’yi eşleştirir ama abc’yi eşleştirmez)
Aynı değiştiriciler Gruplar üzerinde de çalışır (örn. (abc)+) (gruplar için aşağıya bak).
Özel Kümeler ([ ve ] ile oluşturulur)
Karakterleri ayırıcı olmadan köşeli parantez içinde listeleyerek özel karakter kümeleri tanımlayabilirsin. Örneğin a, b, c harfleri ve 1, 2, 3 sayılarından oluşan bir küme için [abc123] yazarız. Bu “bu kümedeki bir karakter” olarak kabul edilir, dolayısıyla birden fazla eşleştirmek için [abc123]* veya [abc123]{2,5} gibi karakter değiştiricileri gerekir.
Özel kümenin başında ^ kullanarak, köşeli parantezde belirttiğin karakterler dışında herhangi bir karakteri kabul ettiğini belirtebilirsin, örneğin [^\\n] yeni satır dışındaki herhangi bir karakteri kabul eder.
Birbiri ardına sıralı olduğunu bildiğin karakterler için (sayılar veya alfabe gibi) araya - koyarak aralık da kullanabilirsin, örneğin [a-zA-Z0-9].
[abc123]{3,} ifadesi a, b, c, ab’yi eşleştirmez ama 111, abc’yi eşleştirir.
Önceden Tanımlı Kümeler (\\s, \\S, \\d, \\D, \\w, \\W)
Aşağıdaki kümeler (basitleştirilmiş) önceden tanımlıdır ve doğrudan kullanılabilir:
\\spratikte[ \\t\\n]ile aynı, “herhangi bir boşluk karakteri” olarak okunur\\Spratikte[^ \\t\\n]ile aynı, “boşluk olmayan herhangi bir karakter” olarak okunur\\dpratikte[0-9]ile aynı, “herhangi bir rakam” olarak okunur\\Dpratikte[^0-9]ile aynı, “rakam olmayan herhangi bir karakter” olarak okunur\\w[a-zA-Z_0-9]’a benzer (Umlaut vb. dahil), “herhangi bir kelime karakteri” olarak okunur\\W[^a-zA-Z_0-9]’a benzer, “kelime karakteri olmayan herhangi bir karakter” olarak okunur
Gruplar (örn. ( ve ), (?<name> ve ))
Grupları “kelimeler” veya “cümleler” gibi düşünebilirsin; herhangi bir değiştirici için varsayılan yapı taşını “karakter”den bir karakter kümesine, yani bir “gruba” dönüştürürler. Örneğin abc* yazmak “bir kez a, bir kez b ve herhangi bir sayıda c” olarak okunur. “Herhangi bir sayıda abc” yazmak istiyorsan şöyle yaparsın: (abc)*. Burada abc bir grup olarak kabul edilir ve regex abcabcabc string’inin tamamını eşleştirir.
Gruplar ayrıca farklı seçenekler belirtmeye de olanak tanır. Bunun için bir grup yazıp farklı kelimeleri | ile ayırırsın, şöyle: (abc|def) — bu “ya abc ya def” olarak okunur ve hem 123abc123 hem de 456def456’yı eşleştirir ama adbecf’yi eşleştirmez.
Bunlar Regex’in bazı alt kısımlarını yakalar ve onlara bir numara veya isim atarlar; bu sayede kod içinde veya değiştirme şablonlarında referans olarak kullanılabilirler. Tipik olarak (.*)@(.*).com gibi yakalama grupları kullanılır ve \\1@\\2.com veya $1@$2.com şeklinde referans verilir (dile bağlı olarak).
Gruplara isim vermek de mümkün, örneğin (?<user>.*)@(?<domain>.*).com yazıp ${user}@${domain}.com şeklinde referans verebilirsin, ama bunlar farklı dillerde farklı şekilde uygulanan ileri düzey özellikler (ve bazılarında mevcut değil).
Eşleşme Değiştiricileri (örn. \\A, \\z, ^, $, Lookahead’ler ve Lookbehind’lar)
Varsayılan olarak bir Regex eşleşmesi, örneğin abc, bir contains metodu gibi çalışır. Ama abc string’inin verilen string’in veya bir satırın başında ya da sonunda olması gerektiğini de belirtebilirsin. Örneğin ^abc‘deki ^ sadece yeni bir satırın başında abc olan string’lerin eşleşmesini sağlar. Bu def\\nabc’yi eşleştirir ama defabc’yi eşleştirmez. abc$’deki $ ise abc’den sonra satır sonu olmasını sağlar. Tüm String boyunca eşleştirme yapmak için \\A ve \\z kullanabilirsin (birden fazla satırı eşleştirir).
Lookahead’ler ve Lookbehind’lar daha ileri düzey bir konu ve özellikle Regex’inin başının veya sonunun belirli bir Regex’le eşleşMEmesini istediğinde faydalıdır. Çoğu durumda Lookahead’li ve Lookbehind’lı Regex’ler Yakalama Grupları ile yeniden yazılabilir, bu yüzden önce Yakalama Grupları olarak yazmayı denemelisin. Bu seçenekler işe yaramazsa Lookaround’lar hakkında okumayı düşün çünkü CPU-yoğun işlemlerdir ve bazı kısıtlamaları vardır (örneğin çoğu değiştiriciyi desteklemezler).
İşte bunlar hakkında öğrenmek için iyi bir kaynak:
Yaygın Tuhaflıklar ve Yeni Regex’leri Doğrulama
Dikkat edilmesi gereken yaygın şeylerden biri, .‘nin çoğu dilde varsayılan olarak yeni satır karakterini eşleştirmemesidir. Ama genellikle bir seçenekle açılabilir; Ruby’de sonuna /m eklenerek belirtilir, bu “noktanın yeni satırları da eşleştirmesini sağla” anlamına gelir.
Ayrıca her dilde String’lerin nasıl çalıştığına bağlı olarak ayrılmış farklı karakterler olduğunu da not et. Örneğin Ruby’de / kaçış karakteri \\/ ile kullanılmalıdır, Swift’te bu kaçış gerekmez ama orada { ve }‘yi \\{ ve \\} ile kaçırman gerekir. Bu tuhaflıklar, başka diller için yazılmış Regex’leri kopyalayıp yapıştırırken önemlidir.
Genel olarak yeni bir Regex yazarken 3 özelliği olan bir web sitesi veya araç kullanmanı öneririm:
Eşleştirmek için örnek bir String ekleme seçeneği.
Bir bakışta şeyleri araştırmak için ekranda görünen bir Regex kopya kağıdı.
Yazdığın regex’i verilen örnek String üzerinde canlı olarak eşleştiren bir araç.
Bunun için kullandığım site şu (arka planda Ruby çalıştırır):
Regex’leri Projelerimde Bugün Nasıl Kullanabilirim?
Regex kullanmak için iyi bir fırsat beklemeye gerek yok, projelerini AnyLint ile Regular Expression kullanarak lint’leyebilirsin (Otomatik Düzeltme desteği dahil):
github.comFlineDev / AnyLintLint anything by combining the power of scripts & regular expressions

