Doğal Dil İşleme+1: 8.Düzenli İfadeler

Düzenli İfadeler

Doğal Dil İşleme yazı serüvenimiz heyecanla devam ediyor. Veri ön işleme, veriyi tanıma olarak adlandırabileceğimiz son yazılarımıza ek olarak, bu yazımızda düzenli ifadeler konusuna girmek istedik. Dışarıdan her ne kadar doğrudan doğal dil işleme konusu olarak görülmese de biz bu konunun çok önemli olduğunu ve eğer bol pratik yapılır, iyi öğrenilirse, sonraki işlemler öncesinde işlerinizi çok kolaylaştıracağını düşünüyoruz. Metin içeren her türlü veri bilimi/ makine öğrenmesi projesinde kullanabileceğiniz bu beceriyi, beceri envanterinize atmanızı şiddetle öneriyoruz.
İyi öğrenmeler…

Kısa bir tanım ve konunun önemi ile başlayalım o halde.

Düzenli ifadeler çoğu belki de tüm modern programlama dillerinde bulunmaktadır. Gelişigüzel bir metin/ifade içerisinde istediğimiz formattaki ifadeleri bulmamızı sağlar. Düzenli ifadeler olmasaydı ardı arkasına birçok if – else yazmak gerekebilirdi. Bu modül, birkaç saatte yapabileceğiniz bir işlemi saniyeler içerisinde sizin yerinize yapabiliyor. [1]

Daha fazla uzatmadan işlemler üzerinden modülü anlamaya çalışalım. Zaten daha sonrası hayalgücünüze kalacak.

A| Temel İşlemler

Bir düzenli(istenen) ifadenin metin içerisinde nasıl aranacağıyla ilgilenir.

1| match()

match() metodu yalnızca, verilen ifadenin metinin başında olup olmadığını kontrol etmek için kullanılabilir. Gerekli olduğunu biz pek görmedik.

Aranılacak kelime, metin ile birlikte re.match metoduna verildi.

1.1 span()

İfadenin konumunu, daha sonrasında kullanılabilir, göze hoş bir biçimde veriyor.

Bu metoda dair daha fazla özellik var ancak bu metodu çok yararlı bulmadığımızdan dolayı ve yazıyı uzatmamak için burada yer vermek istemedik. Dileyenler kaynakçadan ve oluşturduğumuz notebooktan inceleyebilirler.

2| search()

Metinin her yerinde arama yapmak için kullanılır.

1.1 span() ve group() => eşleşme nesneleri?

Aranacak kelime ile birlikte metin , re.search() metoduna verildikten sonra bir değişkene atadık. Daha sonrasında bu değişken üzerinde farklı metodlar kullandık. Bunu ileride sık sık yapacağız.

1.2 Doğrudan aramak

Bu örneği listeler ile vermek istedik. Listelerde bu fonksiyonlar çalışmazlar. Çalışmaları için bir döngü ile içinde gezmeniz gerekir.

Bazen veri bize liste veya farklı veri yapısında gelebilir veya biz işimize geldiği için dönüşüm yaparak öyle kullanmak isteyebiliriz. Veri liste türünde geldiği zaman ise yapacağımız işlem bu şekilde.

3| findall()

Arama sonucunda, bulunan tüm değerleri getirir.
Örnek senaryo: İstenilen ifadenin metinde kaç kere geçtiğini bulmak için kullanabiliriz.

start() ve end()
İstenen ifadeler, metinde en son nerede kullanıldılarsa onların başlangıç ve bitiş indekslerini verirler.

endpos()
Verilen ifade içerisindeki toplam karakter sayısını verir.

Dikkat edilirse baştan veri anlattığımız, kodun çalışma şekli hiç değişmiyor. Sadece fonksiyon isimleri değişiyor.

B| Meta Karakterler

Bir düzenli (belirli özelliklere sahip) ifadenin metin içerisinde nasıl aranacağıyla ilgilenir. Temel işlemlerde istenen ifadeye bakmıştık. Şimdi belirli özellikleri verip gerisini makineye bırakacağız.

Neler var =>  [] . * + ? {} ^ $ \ | ()

Uyarı: Metakarakterlerin, kurallarının kelime için geçerli olduğunu vurguladık defalarca. Bununla (kelime/sözcük) kasıt, boşluk gelmeden önceki tüm ifadedir.
ÖRNEK:
https://web.archive.org/web/201210250 => Burada görüldüğü gibi hiç boşluk yoktur ve bizim kelime dediğimiz yapı ile aynıdır. Kurallar bu yapılar için geçerlidir.

1| Köşeli Parantez []

Girilen karakterler “veya” olarak algılanır, içlerinden yalnızca bir tanesi kelimede bulunmalıdır, daha fazlası veya azı değil.

Görüldüğü üzere, l ve z harflerinin ikisinin birden geçtiği, hiçbirinin geçmediği kombinasyonlar ekrana yansımadı.

2| Nokta .

Kelime uzunluğu boyunca, noktadan geriye doğru her karakterin gelmesi serbesttir.

Görüldüğü gibi “in” den önce ne olduğu farketmeksizin her kelime ekrana basıldı.

3| Yıldız *

Kendinden hemen önce verilen karakterden sıfır (0) veya daha fazla sayıda bulunduğunda çıktı verir. Unutulmaması gereken diğer kural ise,  ondan da önce karakterler verildiyse onların gelmesi zorunludur.

Görüldüğü gibi “engin” kelimesi çıktı olarak görülmedi. Bunun sebebi “s” harfininde kelimelerde bulunma zorluğu.

4| Artı +

Yıldız meta karakteriden farklı olarak, kendinden hemen önce verilen karakterden bir (1) veya daha fazla sayıda bulunduğunda çıktı verir.

Yıldız meta karakterinde “sakin” kelimesi kabul edilmesine rağmen, burada kabul edilmedi. Çünkü “e” harfinin en az 1 kere geçmesi isteniyor.

5| Soru İşareti ?

Yıldız ve artı metakarakterlerinin spesifik özelliklerini alıyor. Yani sadece sıfır (0) veya bir (1) defa geçen ifadeleri ekrana bastırıyor.

Diğerlerinin aksine g harfinin 5 kere geçtiği ifadeyi ekrana bastırmadı.

6| Süslü Parantez {}

Süslü parantez içine yazacağımız sayı ile, hemen öncesinde geçen karakterin, kelime içerisinde kaç kere geçmek istediğini belirtiyoruz. Bu kurala uyanlar ekrana yansıyor.

7| Şapka ^

Sözcüğün hangi karakter ile başlamasını istiyor isek şapka meta karakterinden hemen sonra onu koymamız yeterli. Dikkat edilir ise karakter değil, karakterler ifadesi geçti anlatımda. Yani şapka meta karakterinin yanına, boşluk gelene kadar koyduğunuz tüm karakterleri görmek ister sorguda.

8| Dolar $

Kelimenin hangi karakterler ile bitmesini istiyor isek dolar meta karakterinden hemen önce onu koymamız yeterli. Şapka da geçerli olan son kural burada da geçerlidir ve çok önemlidir. Dİğer meta karakterler ile karıştırılmaması gerekir.

9| Ters Eğik Çizgi \

Kodlama yaparken de görmeye alışkın olduğumuz kaçış karakteridir. Buradaki önemi ise dolar($) gibi meta karakterlerin de kodlarımızda kullanımını sağlamak.

Kodu tek tek inceleyelim.

[0-9]+\$ => Yazının ilerleyen kısımlarında \d olarak karşımıza çıkacak bu ifade bu aralıktaki rakamlardan herhangi birinin geleceğini söylüyor.
Artı (+) meta karakteri ile de en az 1 tane rakam geleceğini ancak daha fazla da gelebileceğinin mümkün olduğunu anlıyoruz.

$ karakterini tek ters eğik çizgi (\) meta karakteri olmadan kullansaydık, makine bunu meta karakter olarak algılayacak ve bize bu kurallar dahilinde bir çıktı yansıtamayacaktı. Ters eğik çizgi kullandığımızda ise $ işareti bir meta karakter değil, bilinen dolar işareti olarak kelimede yerini aldı.

10| Düz Çizgi |

Birden fazla düzenli ifadeyi kullanmamızı sağlar. Verilen düzenli ifadelerden bir tanesini sağlaması yeterlidir.

“selam” kelimesi “se” ifadesi ile başladıkları için,
“metin” kelimesi ise “in” ile bittiği için ekrana yazıldı.
“sezin” ise iki kurala da uyuyor.

11| Parantez ()

Şapka ve dolar meta karakterlerinde üzerinde durduğumuz konu olan, birden fazla karakteri etkileme durumunu, diğer meta karakterlerde nasıl uygulayacağımızı merak etmiş olabilirsiniz. Evet böyle bir şey mümkün. Bunu parantez meta karakteri ile sağlayabiliyoruz.

“c” ve “d” harfleri birlikte sorgulanmıştır. Yıldız (*) meta karakteriyle birlikte şu anlama gelmiştir. => “cd” ifadesi sıfır (0) veya daha fazla geçiyor ise ekrana bastır.

“abdcdef” ifadesi fazladan “d” karakterini içerdiği için ekrana basılmadı.

C| Özel Dizilier

1| \w ve \W

Küçük harf ile başlayan, \w, \s, \d gibi özel diziler bazı işlemleri yapmamızı sağlarken, \W, \S, \D gibi özel diziler ise bu işlemlerin tersini yapmamızı sağlar. Burada işlenecek olarak özel diziler dışında daha fazla özel dizi var. Ancak onlar için kaynaklar müracaat etmenizi tavsiye ediyoruz.

\w metindeki harf, sayı ve alt çizgi için kullanılır. Özel ismi alfanumerik karakterlerdi.  Kuralı sağlayan ifadeleri liste şeklinde basar ekrana.

\W ise geri kalanları alır. Bunların dışında geçen şeyleri saydırmak için kullanabilirsiniz.

Görüldüğü gibi 2 adet boşluk olunca onları bile 2 ayrı eleman olarak aldı. Yıldız karakterini de listeye dahil etti. Bazı özel karakterlerin metinde olmamasını istersen kullanabiliriz. Ancak çok sık işimize yarayacağını söylemeyiz.

2| \s ve \S

İngilizcedeki “space” yani “boşluk” kelimesinin baş harfinden geliyor diye düşünebilir ve kodlayabiliriz zihnimize.

Yani adından da anlaşılabileceği gibi bize boşluk imkanı veriyor. 1 veya daha fazla adet boşluk olmasını istediğimizde/ buna göz yumduğumuzda kural işini yapmış oluyor. Gelin bir örnek ile inceleyelim.

\s sayesinde boşluk olmayan “Bugünkü-konumuz” gibi  ifadeleri elemiş olduk.
[a-z] ile biraz önce \w ile yaptığımız işlemi yapabildik.
.+ => [a-z] den en az 1 tane ama istediğin kadar alabilirsin demiş olduk.

3| \d ve \D

İngilizcedeki “double” yani “ondalık” kelimesinin baş harfidir. [0-9] arasındaki sayıları yani rakamları ifade eder. Rakamları tespit etmek için kullanırız.

Önce \d özel dizisini görelim.

\d+ => En az 1 tane sayı geçsin
\s => 1 adet boşluk olsun
\w => En az 1 adet alfanumerik değer geçsin

\D özel dizisi ise tahmin edileceği üzere, bu işlemin tersini vermekte yani sayı olmayan değerleri ekrana bastırmaktadır.

Böylece ifademizdeki gereksiz sayıları atmış olduk.

D| Ekstralar

 compile() => re.I ve re.S kullanımı

Düzenli ifadeler karakter dizilerine göre biraz daha yavaş çalışırlar.
Ancak düzenli ifadelerin işleyişini hızlandırmanın da bazı yolları vardır. Bu yollardan biri de compile() metodunu kullanmaktır.

re.I sayesinde hem büyük harf hem de küçük harf ile başlayan ifadeleri getirmiş olduk.

Nokta (.) meta karakteri sonraki satırda aramada kullanılamıyor. Bunu sağlamak için böyle bir metot var.

 sub() + subn()

Çok bilinen replace() metodu yerine kullanılabilir. Daha karmaşık metinlerde tercih edilir.

subn() ile de kaç değişiklik yapıldığı gözükür

“nisan” ve “Nisan” => “ekim” oldu ve toplamda 2 adet değişiklik yapılmış oldu.

E| Örnek Uygulama

Web kazıma ve düzenli ifadeler ile ilgili işlemleri yapabilmek için gerekli bazı kurulumları ve veriyi hazır hale getirmek işlemleri yapıldıktan sonra düzenli ifadeler devreye giriyor.

.+html => En az bir karakter ile başlayan, sınırsız uzunluğa sahip(boşluk olmadan) ve html ile biten ifadeleri getir.

(.+) => En az bir karakter ile başlayan, sınırsız uzunluğa sahip ancak bunları bir bütün şeklinde sağlayan ifadeyi getir.

Yazbel Python sitesinden aldığımız bu örnek, şimdiye kadar öğrendiğimiz bir çok özelliği bir arada sunuyor. Biz birkaçını açıkladık. Geri kalan kısımlar size ödev 🙂

Kodların bulunduğu notebook

Serinin Diğer Yazıları;
Doğal Dil İşlemeye (DDİ) Giriş
DDİ’nin Arka Planı, Zorlukları, Geleceği
Doğal Dil İşleme ve String İşlemleri
Doğal Dil İşleme Kütüphaneleri
DDİ’de Veri Ön İşleme-1
DDİ’de Veri Ön İşleme-2
DDİ’de Part of Speech Tagging ve Saklı Markov Modeli

Yazarlar: Mustafa Selim ÖZEN, Saygın YILDIZ

Kaynaklar

[1] https://www.sinanerdinc.com/python-re-modulu
[2] https://python-istihza.yazbel.com/standart_moduller/regex.html
[3] https://www.youtube.com/watch?v=sSD_xCade-g&t=320s
[4] https://alhydrtprk.medium.com/python-re-regular-expression-mod%C3%BCl%C3%BC-6dec531a8434
[5] https://erdincuzun.com/ileri-python/regular-expressions-duzenli-ifadeler/
[6] https://www.tutorialspoint.com/python/python_reg_expressions.htm
[7] https://www.w3schools.com/python/python_regex.asp
[8] https://docs.python.org/3/howto/regex.html
[9] https://regex101.com/