Düzenli ifadeler kullanarak gelişmiş JavaScript desen eşleştirmeyi keşfedin. Etkili ve sağlam kod için regex sözdizimi, pratik uygulamalar ve optimizasyon tekniklerini öğrenin.
JavaScript'te Düzenli İfadelerle Desen Eşleştirme: Kapsamlı Bir Rehber
Düzenli ifadeler (regex), JavaScript'te desen eşleştirme ve metin işleme için güçlü bir araçtır. Geliştiricilerin tanımlanmış desenlere göre dizeleri aramasına, doğrulamasına ve dönüştürmesine olanak tanır. Bu rehber, JavaScript'teki düzenli ifadelere sözdizimi, kullanım ve ileri düzey teknikleri kapsayan kapsamlı bir genel bakış sunmaktadır.
Düzenli İfadeler Nedir?
Düzenli ifade, bir arama deseni tanımlayan bir karakter dizisidir. Bu desenler, dizeleri eşleştirmek ve işlemek için kullanılır. Düzenli ifadeler, programlamada aşağıdaki gibi görevler için yaygın olarak kullanılır:
- Veri Doğrulama: Kullanıcı girdisinin belirli formatlara (ör. e-posta adresleri, telefon numaraları) uymasını sağlamak.
- Veri Çıkarma: Metinden belirli bilgileri almak (ör. tarihleri, URL'leri veya fiyatları çıkarmak).
- Arama ve Değiştirme: Karmaşık desenlere göre metin bulma ve değiştirme.
- Metin İşleme: Tanımlanmış kurallara göre dizeleri bölme, birleştirme veya dönüştürme.
JavaScript'te Düzenli İfadeler Oluşturma
JavaScript'te düzenli ifadeler iki şekilde oluşturulabilir:
- Bir Düzenli İfade Literali Kullanarak: Deseni ileri eğik çizgiler (
/) arasına alın. RegExpYapıcısını Kullanarak: Deseni bir dize olarak içeren birRegExpnesnesi oluşturun.
Örnek:
// Düzenli ifade literali kullanarak
const regexLiteral = /hello/;
// RegExp yapıcısını kullanarak
const regexConstructor = new RegExp("hello");
İki yöntem arasındaki seçim, desenin derleme zamanında mı bilindiğine yoksa dinamik olarak mı oluşturulduğuna bağlıdır. Desen sabit ve önceden biliniyorsa literal gösterimi kullanın. Desen programatik olarak oluşturulması gerektiğinde, özellikle değişkenleri içerirken yapıcıyı kullanın.
Temel Regex Sözdizimi
Düzenli ifadeler, eşleştirilecek deseni temsil eden karakterlerden oluşur. İşte bazı temel regex bileşenleri:
- Birebir Karakterler: Karakterlerin kendisiyle eşleşir (ör.
/a/, 'a' karakteriyle eşleşir). - Meta Karakterler: Özel anlamları vardır (ör.
.,^,$,*,+,?,[],{},(),\,|). - Karakter Sınıfları: Karakter kümelerini temsil eder (ör.
[abc], 'a', 'b' veya 'c' ile eşleşir). - Niceleyiciler: Bir karakterin veya grubun kaç kez tekrar etmesi gerektiğini belirtir (ör.
*,+,?,{n},{n,},{n,m}). - Çapalar: Dizedeki konumlarla eşleşir (ör.
^başlangıçla,$sonla eşleşir).
Yaygın Meta Karakterler:
.(nokta): Yeni satır hariç herhangi bir tek karakterle eşleşir.^(şapka): Dizenin başlangıcıyla eşleşir.$(dolar): Dizenin sonuyla eşleşir.*(yıldız): Önceki karakterin veya grubun sıfır veya daha fazla tekrarıyla eşleşir.+(artı): Önceki karakterin veya grubun bir veya daha fazla tekrarıyla eşleşir.?(soru işareti): Önceki karakterin veya grubun sıfır veya bir tekrarıyla eşleşir. İsteğe bağlı karakterler için kullanılır.[](köşeli parantezler): Bir karakter sınıfı tanımlar, parantez içindeki herhangi bir tek karakterle eşleşir.{}(süslü parantezler): Eşleşecek tekrar sayısını belirtir.{n}tam olarak n kez eşleşir,{n,}n veya daha fazla kez eşleşir,{n,m}n ile m kez arasında eşleşir.()(parantezler): Karakterleri birlikte gruplar ve eşleşen alt dizeyi yakalar.\(ters eğik çizgi): Meta karakterlerden kaçış sağlar, böylece onları birebir eşleştirebilirsiniz.|(dikey çizgi): "Veya" operatörü olarak işlev görür, kendinden önceki veya sonraki ifadeyle eşleşir.
Karakter Sınıfları:
[abc]: a, b veya c karakterlerinden herhangi biriyle eşleşir.[^abc]: a, b veya c *olmayan* herhangi bir karakterle eşleşir.[a-z]: a'dan z'ye kadar herhangi bir küçük harfle eşleşir.[A-Z]: A'dan Z'ye kadar herhangi bir büyük harfle eşleşir.[0-9]: 0'dan 9'a kadar herhangi bir rakamla eşleşir.[a-zA-Z0-9]: Herhangi bir alfanümerik karakterle eşleşir.\d: Herhangi bir rakamla eşleşir ([0-9]ile eşdeğerdir).\D: Rakam olmayan herhangi bir karakterle eşleşir ([^0-9]ile eşdeğerdir).\w: Herhangi bir kelime karakteriyle eşleşir (alfanümerik artı alt çizgi;[a-zA-Z0-9_]ile eşdeğerdir).\W: Kelime olmayan herhangi bir karakterle eşleşir ([^a-zA-Z0-9_]ile eşdeğerdir).\s: Herhangi bir boşluk karakteriyle eşleşir (boşluk, sekme, yeni satır vb.).\S: Boşluk olmayan herhangi bir karakterle eşleşir.
Niceleyiciler:
*: Önceki öğeyle sıfır veya daha fazla kez eşleşir. Örneğin,a*"", "a", "aa", "aaa" vb. ile eşleşir.+: Önceki öğeyle bir veya daha fazla kez eşleşir. Örneğin,a+"a", "aa", "aaa" ile eşleşir, ancak "" ile eşleşmez.?: Önceki öğeyle sıfır veya bir kez eşleşir. Örneğin,a?"" veya "a" ile eşleşir.{n}: Önceki öğeyle tam olarak *n* kez eşleşir. Örneğin,a{3}"aaa" ile eşleşir.{n,}: Önceki öğeyle *n* veya daha fazla kez eşleşir. Örneğin,a{2,}"aa", "aaa", "aaaa" vb. ile eşleşir.{n,m}: Önceki öğeyle *n* ile *m* kez arasında (dahil) eşleşir. Örneğin,a{2,4}"aa", "aaa" veya "aaaa" ile eşleşir.
Çapalar:
^: Dizenin başlangıcıyla eşleşir. Örneğin,^Hello"Hello" ile *başlayan* dizelerle eşleşir.$: Dizenin sonuyla eşleşir. Örneğin,World$"World" ile *biten* dizelerle eşleşir.\b: Bir kelime sınırı ile eşleşir. Bu, bir kelime karakteri (\w) ile kelime olmayan bir karakter (\W) arasındaki veya dizenin başı ya da sonundaki konumdur. Örneğin,\bword\b"word" kelimesinin tamamıyla eşleşir.
Bayraklar:
Regex bayrakları, düzenli ifadelerin davranışını değiştirir. Regex literalinin sonuna eklenirler veya RegExp yapıcısına ikinci bir argüman olarak geçirilirler.
g(global): Desenin sadece ilkini değil, tüm tekrarlarını eşleştirir.i(ignore case): Büyük/küçük harfe duyarsız eşleştirme yapar.m(multiline): Çok satırlı modu etkinleştirir, burada^ve$her satırın (\nile ayrılmış) başlangıcı ve sonuyla eşleşir.s(dotAll): Noktanın (.) yeni satır karakterleriyle de eşleşmesine izin verir.u(unicode): Tam Unicode desteğini etkinleştirir.y(sticky): Yalnızca regex'inlastIndexözelliği tarafından belirtilen dizinden eşleşir.
JavaScript Regex Metotları
JavaScript, düzenli ifadelerle çalışmak için birkaç metot sağlar:
test(): Bir dizenin desene uyup uymadığını test eder.trueveyafalsedöndürür.exec(): Bir dizede bir eşleşme arar. Eşleşen metni ve yakalanan grupları içeren bir dizi veya eşleşme bulunamazsanulldöndürür.match(): Bir dizenin düzenli bir ifadeye karşı eşleştirilmesinin sonuçlarını içeren bir dizi döndürür.gbayrağı ile ve olmadan farklı davranır.search(): Bir dizede bir eşleşme arar. İlk eşleşmenin dizinini veya eşleşme bulunamazsa -1 döndürür.replace(): Bir desenin tekrarlarını bir değiştirme dizesiyle veya değiştirme dizesini döndüren bir fonksiyonla değiştirir.split(): Bir dizeyi, düzenli bir ifadeye dayanarak bir alt dize dizisine böler.
Regex Metotlarını Kullanan Örnekler:
// test()
const regex = /hello/;
const str = "hello world";
console.log(regex.test(str)); // Çıktı: true
// exec()
const regex2 = /hello (\w+)/;
const str2 = "hello world";
const result = regex2.exec(str2);
console.log(result); // Çıktı: ["hello world", "world", index: 0, input: "hello world", groups: undefined]
// 'g' bayrağı ile match()
const regex3 = /\d+/g; // Genel olarak bir veya daha fazla rakamı eşleştirir
const str3 = "There are 123 apples and 456 oranges.";
const matches = str3.match(regex3);
console.log(matches); // Çıktı: ["123", "456"]
// 'g' bayrağı olmadan match()
const regex4 = /\d+/;
const str4 = "There are 123 apples and 456 oranges.";
const match = str4.match(regex4);
console.log(match); // Çıktı: ["123", index: 11, input: "There are 123 apples and 456 oranges.", groups: undefined]
// search()
const regex5 = /world/;
const str5 = "hello world";
console.log(str5.search(regex5)); // Çıktı: 6
// replace()
const regex6 = /world/;
const str6 = "hello world";
const newStr = str6.replace(regex6, "JavaScript");
console.log(newStr); // Çıktı: hello JavaScript
// Bir fonksiyon ile replace()
const regex7 = /(\d+)-(\d+)-(\d+)/;
const str7 = "Today's date is 2023-10-27";
const newStr2 = str7.replace(regex7, (match, year, month, day) => {
return `${day}/${month}/${year}`;
});
console.log(newStr2); // Çıktı: Today's date is 27/10/2023
// split()
const regex8 = /, /;
const str8 = "apple, banana, cherry";
const arr = str8.split(regex8);
console.log(arr); // Çıktı: ["apple", "banana", "cherry"]
İleri Düzey Regex Teknikleri
Yakalama Grupları:
Parantezler (), düzenli ifadelerde yakalama grupları oluşturmak için kullanılır. Yakalanan gruplar, eşleşen metnin belirli kısımlarını çıkarmanıza olanak tanır. exec() ve match() metotları, ilk öğenin tüm eşleşme olduğu ve sonraki öğelerin yakalanan gruplar olduğu bir dizi döndürür.
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match[0]); // Çıktı: 2023-10-27 (Eşleşmenin tamamı)
console.log(match[1]); // Çıktı: 2023 (İlk yakalanan grup - yıl)
console.log(match[2]); // Çıktı: 10 (İkinci yakalanan grup - ay)
console.log(match[3]); // Çıktı: 27 (Üçüncü yakalanan grup - gün)
İsimli Yakalama Grupları:
ES2018, (? sözdizimini kullanarak yakalama gruplarına isimler atamanıza olanak tanıyan isimli yakalama gruplarını tanıttı. Bu, kodu daha okunabilir ve sürdürülebilir hale getirir.
const regex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match.groups.year); // Çıktı: 2023
console.log(match.groups.month); // Çıktı: 10
console.log(match.groups.day); // Çıktı: 27
Yakalamayan Gruplar:
Bir regex'in bölümlerini yakalamadan gruplamanız gerekiyorsa (ör. bir gruba niceleyici uygulamak için), (?:...) sözdizimiyle yakalamayan bir grup kullanabilirsiniz. Bu, yakalanan gruplar için gereksiz bellek ayırmayı önler.
const regex = /(?:https?:\/\/)?([\w\.]+)/; // Bir URL'yi eşleştirir ancak yalnızca alan adını yakalar
const url = "https://www.example.com/path";
const match = regex.exec(url);
console.log(match[1]); // Çıktı: www.example.com
İleri/Geri Bakma (Lookarounds):
İleri/geri bakmalar, bir dizede bir konumu, o konumu önceleyen (geriye bakma) veya takip eden (ileriye bakma) bir desene göre eşleştiren, ancak ileri/geri bakma desenini eşleşmenin kendisine dahil etmeyen sıfır genişlikli iddialardır.
- Pozitif İleriye Bakma:
(?=...)İleriye bakma içindeki desen mevcut konumu *takip ediyorsa* eşleşir. - Negatif İleriye Bakma:
(?!...)İleriye bakma içindeki desen mevcut konumu *takip etmiyorsa* eşleşir. - Pozitif Geriye Bakma:
(?<=...)Geriye bakma içindeki desen mevcut konumu *önceliyorsa* eşleşir. - Negatif Geriye Bakma:
(? Geriye bakma içindeki desen mevcut konumu *öncelemiyorsa* eşleşir.
Örnek:
// Pozitif İleriye Bakma: Fiyatı yalnızca USD takip ettiğinde al
const regex = /\d+(?= USD)/;
const text = "The price is 100 USD";
const match = text.match(regex);
console.log(match); // Çıktı: ["100"]
// Negatif İleriye Bakma: Kelimeyi yalnızca bir sayı takip etmediğinde al
const regex2 = /\b\w+\b(?! \d)/;
const text2 = "apple 123 banana orange 456";
const matches = text2.match(regex2);
console.log(matches); // Çıktı: null çünkü match() 'g' bayrağı olmadan sadece ilk eşleşmeyi döndürür, bu da ihtiyacımız olan şey değil.
// düzeltmek için:
const regex3 = /\b\w+\b(?! \d)/g;
const text3 = "apple 123 banana orange 456";
const matches3 = text3.match(regex3);
console.log(matches3); // Çıktı: [ 'banana' ]
// Pozitif Geriye Bakma: Değeri yalnızca $ işareti önünde geldiğinde al
const regex4 = /(?<=\$)\d+/;
const text4 = "The price is $200";
const match4 = text4.match(regex4);
console.log(match4); // Çıktı: ["200"]
// Negatif Geriye Bakma: Kelimeyi yalnızca 'not' kelimesi önünde gelmediğinde al
const regex5 = /(?
Geri Referanslar:
Geri referanslar, aynı düzenli ifade içinde daha önce yakalanan gruplara başvurmanıza olanak tanır. \1, \2 vb. sözdizimini kullanırlar, burada sayı yakalanan grup numarasına karşılık gelir.
const regex = /([a-z]+) \1/;
const text = "hello hello world";
const match = regex.exec(text);
console.log(match); // Çıktı: ["hello hello", "hello", index: 0, input: "hello hello world", groups: undefined]
Düzenli İfadelerin Pratik Uygulamaları
E-posta Adreslerini Doğrulama:
Düzenli ifadelerin yaygın bir kullanım durumu e-posta adreslerini doğrulamaktır. Mükemmel bir e-posta doğrulama regex'i son derece karmaşık olsa da, işte basitleştirilmiş bir örnek:
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
console.log(emailRegex.test("test@example.com")); // Çıktı: true
console.log(emailRegex.test("invalid-email")); // Çıktı: false
console.log(emailRegex.test("test@sub.example.co.uk")); // Çıktı: true
Metinden URL'leri Çıkarma:
Bir metin bloğundan URL'leri çıkarmak için düzenli ifadeleri kullanabilirsiniz:
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
const text = "Visit our website at https://www.example.com or check out http://blog.example.org.";
const urls = text.match(urlRegex);
console.log(urls); // Çıktı: ["https://www.example.com", "http://blog.example.org"]
CSV Verilerini Ayrıştırma:
Düzenli ifadeler, CSV (Virgülle Ayrılmış Değerler) verilerini ayrıştırmak için kullanılabilir. İşte tırnak içine alınmış alanları işleyen bir CSV dizesini bir değerler dizisine bölme örneği:
const csvString = 'John,Doe,"123, Main St",New York';
const csvRegex = /(?:"([^"]*(?:""[^"]*)*)")|([^,]+)/g; //Düzeltilmiş CSV regex
let values = [];
let match;
while (match = csvRegex.exec(csvString)) {
values.push(match[1] ? match[1].replace(/""/g, '"') : match[2]);
}
console.log(values); // Çıktı: ["John", "Doe", "123, Main St", "New York"]
Uluslararası Telefon Numarası Doğrulama
Uluslararası telefon numaralarını doğrulamak, değişen formatlar ve uzunluklar nedeniyle karmaşıktır. Sağlam bir çözüm genellikle bir kütüphane kullanmayı gerektirir, ancak basitleştirilmiş bir regex temel doğrulama sağlayabilir:
const phoneRegex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
console.log(phoneRegex.test("+1 555 123 4567")); // Çıktı: true (ABD Örneği)
console.log(phoneRegex.test("+44 20 7946 0500")); // Çıktı: true (Birleşik Krallık Örneği)
console.log(phoneRegex.test("+81 3 3224 5000")); // Çıktı: true (Japonya Örneği)
console.log(phoneRegex.test("123-456-7890")); // Çıktı: false
Parola Güçlülüğü Doğrulama
Düzenli ifadeler, parola güçlülüğü politikalarını uygulamak için kullanışlıdır. Aşağıdaki örnek, minimum uzunluk, büyük harf, küçük harf ve bir sayıyı kontrol eder.
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("P@ssword123")); // Çıktı: true
console.log(passwordRegex.test("password")); // Çıktı: false (büyük harf veya sayı yok)
console.log(passwordRegex.test("Password")); // Çıktı: false (sayı yok)
console.log(passwordRegex.test("Pass123")); // Çıktı: false (küçük harf yok)
console.log(passwordRegex.test("P@ss1")); // Çıktı: false (8 karakterden az)
Regex Optimizasyon Teknikleri
Düzenli ifadeler, özellikle karmaşık desenler veya büyük girdiler için hesaplama açısından maliyetli olabilir. İşte regex performansını optimize etmek için bazı teknikler:
- Spesifik Olun: Amaçlanandan daha fazlasını eşleştirebilecek aşırı genel desenler kullanmaktan kaçının.
- Çapaları Kullanın: Mümkün olduğunda regex'i dizenin başına veya sonuna sabitleyin (
^,$). - Geri İzlemeden (Backtracking) Kaçının: Uygun olduğunda sahiplenici niceleyiciler (ör.
+yerine++) veya atomik gruplar ((?>...)) kullanarak geri izlemeyi en aza indirin. - Bir Kez Derleyin: Aynı regex'i birden çok kez kullanıyorsanız, bir kez derleyin ve
RegExpnesnesini yeniden kullanın. - Karakter Sınıflarını Akıllıca Kullanın: Karakter sınıfları (
[]) genellikle alternatiflerden (|) daha hızlıdır. - Basit Tutun: Anlaşılması ve bakımı zor olan aşırı karmaşık regex'lerden kaçının. Bazen karmaşık bir görevi birden çok basit regex'e bölmek veya diğer dize işleme tekniklerini kullanmak daha verimli olabilir.
Yaygın Regex Hataları
- Meta Karakterlerden Kaçmayı Unutmak:
.,*,+,?,$,^,(,),[,],{,},|ve\gibi özel karakterleri birebir eşleştirmek istediğinizde bunlardan kaçmayı ihmal etmek. .(Nokta) Aşırı Kullanımı: Nokta, herhangi bir karakterle (bazı modlarda yeni satır hariç) eşleşir, bu da dikkatli kullanılmazsa beklenmedik eşleşmelere yol açabilir. Mümkün olduğunda karakter sınıfları veya diğer daha kısıtlayıcı desenler kullanarak daha spesifik olun.- Açgözlülük: Varsayılan olarak,
*ve+gibi niceleyiciler açgözlüdür ve mümkün olduğunca çok eşleşir. Mümkün olan en kısa dizeyi eşleştirmeniz gerektiğinde tembel niceleyiciler (*?,+?) kullanın. - Çapaları Yanlış Kullanmak:
^(dize/satır başı) ve$(dize/satır sonu) davranışını yanlış anlamak, yanlış eşleşmelere yol açabilir. Çok satırlı dizelerle çalışırken ve^ile$'ın her satırın başı ve sonuyla eşleşmesini istediğinizdem(çok satırlı) bayrağını kullanmayı unutmayın. - Kenar Durumları Göz Ardı Etmek: Tüm olası girdi senaryolarını ve kenar durumlarını dikkate almamak hatalara yol açabilir. Regex'lerinizi boş dizeler, geçersiz karakterler ve sınır koşulları dahil olmak üzere çeşitli girdilerle kapsamlı bir şekilde test edin.
- Performans Sorunları: Aşırı karmaşık ve verimsiz regex'ler oluşturmak, özellikle büyük girdilerle performans sorunlarına neden olabilir. Daha spesifik desenler kullanarak, gereksiz geri izlemeden kaçınarak ve tekrar tekrar kullanılan regex'leri derleyerek regex'lerinizi optimize edin.
- Karakter Kodlamasını Görmezden Gelmek: Karakter kodlamalarını (özellikle Unicode) doğru bir şekilde işlememek beklenmedik sonuçlara yol açabilir. Doğru eşleşmeyi sağlamak için Unicode karakterlerle çalışırken
ubayrağını kullanın.
Sonuç
Düzenli ifadeler, JavaScript'te desen eşleştirme ve metin işleme için değerli bir araçtır. Regex sözdiziminde ve tekniklerinde ustalaşmak, veri doğrulamadan karmaşık metin işlemeye kadar geniş bir yelpazedeki sorunları verimli bir şekilde çözmenizi sağlar. Bu rehberde tartışılan kavramları anlayarak ve gerçek dünya örnekleriyle pratik yaparak, JavaScript geliştirme becerilerinizi geliştirmek için düzenli ifadeleri kullanmada yetkin olabilirsiniz.
Unutmayın ki düzenli ifadeler karmaşık olabilir ve onları regex101.com veya regexr.com gibi çevrimiçi regex test edicileri kullanarak kapsamlı bir şekilde test etmek genellikle yardımcı olur. Bu, eşleşmeleri görselleştirmenize ve herhangi bir sorunu etkili bir şekilde ayıklamanıza olanak tanır. İyi kodlamalar!