11 Temmuz 2013 Perşembe

Bu bölümde doğrudan düzenli ifadelerin değil, düzenli ifadeler ile oluşan eşleşme nesnelerinin metotlarını göreceğiz. Gelin ilk önce hangi metotlar var, onlara bir bakalım.
import re

karakter = "Python"

nesne = re.match("Python",karakter)
for i in dir(nesne):
    if not i.startswith("__"):
        print i
end
endpos
expand
group
groupdict
groups
lastgroup
lastindex
pos
re
regs
span
start
string
Gördüğünüz gibi oldukça metod var. Bunlardan bazılarını beraber inceleyeceğiz.
group() Metodu
Bu metodu daha önce de sık sık kullanmıştık. Hatırlarsınız ki group() metodu düzenli ifadeler ile eşleştirdiğimiz karakter dizilerini görmemizi sağlıyordu.
"()" metakarakterini kullanarak group() metodu ile ilgili bir kaç örnek verelim.
#-*-coding:utf-8-*-

import re

karakter = "Python programlama dilini öğreniyorum"

duzenli = re.search("(Python) (programlama) (dilini) (öğreniyorum)",karakter)
Bu örnekte "()" metakarakterini kullanarak birden çok eşleştirme yaptık. group() metodunu kullanarak bunları ekrana yazdırabiliriz.
print duzenli.group()
Python programlama dilini öğreniyorum

print duzenli.group(0)
Python programlama dilini öğreniyorum
Gördüğünüz gibi group() metodunu kullanarak yaptığımız eşleştirmelerin hepsini ekrana yazdırdık. Dikkatinizi çekmiş olmalı ki group(0) şeklinde kullanım da group() ile aynı sonucu verdi. Yani group(0) şeklinde kullanım da tüm eşleştirmeleri geriye döndürür.
print duzenli.group(1)
Python

print duzenli.group(2)
programlama
Kısacası group() metodu eşleştirmeleri gruplamamızı sağlıyor.
groups() Metodu
groups() metodu eşleştirme yaparken "()" metakarakterini kullanarak oluşturduğumuz bütün grupları demet olarak geriye döndürür.
print duzenli.groups()
karakter = "Python programlama dilini ogreniyorum"

duzenli = re.search("(Python) (programlama) (dilini) (ogreniyorum)",karakter)

('Python', 'programlama', 'dilini', 'ogreniyorum')
Gördüğünüz gibi groups() metodunu kullanarak oluşturduğumuz grupları demet şeklinde elde etmiş olduk. Demetlerin tüm özellikleri burada oluşturduğumuz demet içinde aynen geçerlidir.
if duzenli.groups().count("Python"):
    print "Yapılan gruplamada 'Python' ifadesi bulunmuştur."
Yapılan gruplamada 'Python' ifadesi bulunmuştur. 
Burada demetlerin "count" özelliğini kullanarak sorgulama işlemi yaptık.
Özel Diziler
Bu bölümde Python'da metakarakterler dışında düzenli ifadeler ile kullanılan bazı özel ifadelere değineceğiz.
Bu özel ifadeler:
\s => Boşluk karakterini yakalar.
\d => Ondalık sayıları yakalar.
\w => Alfanümerik karakterler ve "_" karakterini yakalar.
\s Özel Dizisi
import re

liste = ['Parker','Dünyalar Savaşı','Hangover','Hızli Ofkeli','Zor Olüm']

for i in liste:
    if re.search(u"[A-Za-z]+\s[A-Za-z]+",i):
        print i
Dünyalar Savaşı
Hizli Ofkeli
Zor Olüm
Bu örnekte büyük veya küçük harflerden oluşan, boşluk ile devam eden, ardından tekrar büyük veya küçük harflerden oluşan liste ögelerini ayıkladık. Yani iki kelimeli film isimlerini yakalamış olduk. Burada boşluk karakterini "/s" özel dizisi ile yakaladık.
\d Özel Dizisi
Bugüne kadar yaptığımız örneklerde ondalık sayıları kullanmak için [0-9] ifadesini kullandık. Aynı eşleştirmeyi "\d" özel dizisi ile de yapabilmekteyiz. Bir önceki örneğimizi şu şekilde değiştirelim.
liste = ['Parker','2 Guns','Hangover','300 Spartalı','Zor Olüm']

for i in liste:
    if re.search(u"\d+\s[A-Za-z]+",i):
        print i
2 Guns
300 Spartalı
Gördüğünüz gibi sayı ile başlayan filmleri bulmak için "\d" özel dizisini kullandık ve ardından boşluk ile devam etmesi için "\s" özel dizisini kullandık.
\w Özel Dizisi
ifade = "a21_?ab_%+"

print re.search("\w*",ifade).group()
a21_
Burada "\w" özel dizisini kullanarak alfanümerik karakterleri ve "_" karakterini yakalamış olduk. Bu özel dizi "[A-Za-z0-9_]" ifadesi ile aynı anlama gelmektedir. Gördüğünüz gibi işimizi ne kadar da kısaltmış oluyoruz.
Python'da bulunan bu özel dizilerin birde büyük harfli olanları vardır. Büyük harfli olanlar küçük harfli özel dizilerin yaptığı işin tam tersini yaparlar.

%S => Boşluk olmayan karakterleri yakalar.
%D => Ondalık sayı olmayan karakterleri yakalar.
%W => Alfanümerik olmayan ve "_" olmayan karakterleri yakalar.

Verdiğimiz örneklere göre bunlar da gayet net bir şekilde anlaşılıyor. Bu yüzden Ondalık dizilerin büyükleri için özel olarak örnek verilmeyecektir.
Düzenli İfadelerin Derlenmesi
compile() Metodu
Düzenli ifadeler karakter dizilerine göre daha yavaştırlar. Düzenli ifadelerin daha hazlı çalışmasını sağlamak için compile() metodu kullanılabilir. compile() metodu kullanılarak düzenli ifade kalıpları kullanılmadan önce derlenerek daha hızlı çalışırlar. Bu metot küçük boyutlu projelerde çok hissedilir bir fark yaratmasa da büyük boyutlu projeler için çok faydalı olacaktır.
import re

derle = re.compile("[A-Za-z]+\s[A-Za-z]+")
 
liste = ['Parker','Dünyalar Savaşı','Hangover','Hızli Ofkeli','Zor Olüm']

for i in liste:
    if derle.search(i):
        print i
Dünyalar Savaşı
Hızli Ofkeli
Zor Olüm
Özel dizileri kullanırken verdiğimiz örneği biraz değiştirerek tekrardan kullandık. Dikkat ederseniz düzenli ifade kalıbını compile() metodu içerisine yazarak ilk önce derleme işlemini yerine getirdik. search() metodunu kullanırken ise artık re.search() kalıbını değil de yeni oluşturduğumuz derle değişkenini kullanarak derle.search() ifadesini kullandık. derle.search() kalıbı içerisinde ise artık düzenli ifadeye yer vermedik, sadece karakter dizisini yazmış olmamamız yeterli oldu.
compile() ile Derleme Seçenekleri
compile() metodu ile derleme yapmayı gördük. Şimdi compile() ile bize sunulan bazı seçeneklere bakacağız. re.IGNORECASE veya re.I
Python programlama dili büyük küçük harflere duyarlıdır. Yani Python için "Python" ve "python" farklı karakter dizileridir. Eğer biz "Python" düzenli ifadesini bulmak istersek, bulduğumuz karakter dizileri arasında "python" karakter dizisini göremeyiz. İşte bu duyarlılığı ortadan kaldırmak için "re.IGNORECASE" veya "re.I" derleme seçeneklerini kullanabiliriz.
#-*-coding:utf8-*-

import re

metin ="""Bilgisayarlar çok farklı biçimlerde karşımıza çıkabilirler. 
20. yüzyılın ortalarındaki ilk bilgisayarlar büyük bir oda büyüklüğünde olup, 
günümüz bilgisayarlarından yüzlerce kat daha fazla güç tüketiyorlardı. 
21. yüzyılın başına varıldığında ise bilgisayarlar bir kol saatine sığacak ve 
küçük bir pil ile çalışacak duruma geldiler. Bu kadar küçük imal edilebilmelerinin 
temel nedeni 1969 yılında yarı iletkenler ile çok küçük alanlara sığdırılabilen 
devreler yapılabilmesidir. Şu anda kullandığımız bilgisayarlar Intel'in ilk işlemci
unvanına sahip olan 4004'den sonra bilgisayar teknolojisi hız kazanmıştır.
Toplumumuz kişisel bilgisayarı ve onun taşınabilir eşdeğeri,
dizüstü bilgisayarını, bilgi çağının simgeleri olarak tanıdılar ve 
bilgisayar kavramıyla özdeşleştirdiler. Günümüzde çok yaygın kullanılmaktadırlar. 
Bilgisayarın temel çalışma prensibi ikili sayı sistemi yani sadece 0 ve 1 den oluşan kodlamalardır."""

derle = re.compile("bilgisayar",re.I)
print derle.findall(metin)

['Bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'Bilgisayar']
Gördüğünüz gibi elimizde bulunan bir metindeki "bilgisayar" kelimelerini büyük,küçük harf ayırt etmeden bulmuş olduk. Eğer re.I seçeneğini kullanmış olmasaydık, çıktı olarak sadece "bilgisayar" kelimesini alırdık. re.IGNORECASE de re.I seçeneği ile aynı işleve sahiptir.
re.DOTALL veya re.S
Metekarakterler arasında "." metakarakterini açıklaraken, yeni satır karakteri hariç herhangi bir karakterin yerini tuttuğunu söylemiştik.
#-*-coding:utf8-*-

import re

metin = "Python; \ngüçlü bir programlama dilidir"

print re.search("Python.*",metin).group()
Python;
Burada gördüğünüz gibi "." metakarakteri yeni satır(\n) karakterinin yerini tutmadığı için bize sadece "Python;" ifadesini geriye döndürdü. İşte biz "." metakarakterine bu özelliği de kazandırmak istersek re.DOTALL veya re.S özelliklerinden birini kullanabiliriz.
import re

metin = "Python;\ngüçlü bir programlama dilidir."
derle = re.compile("Python.*",re.DOTALL)

print derle.search(metin).group()
Python;
güçlü bir programlama dilidir.
Artık "." metakarakteri yeni satır karakterini de algıladı ve bize istediğimiz sonucu döndürdü. re.DOTALL seçeneği ile re.S seçeneği aynı işlevi yapmaktadır.
re.UNICODE veya re.U
Python'da düzenli ifadeleri kullanırken Türkçe karakter problemi ile karşılaşırız. Şu örneği inceleyelim;
#-*-coding:utf8-*-

import re

liste = ["otobüs","otomobil","kamyon","minibüs"]

for i in liste:
    print re.search("\w*",i).group()
otob
otomobil
kamyon
minib
Gördüğünüz gibi Python Türkçe karakterlerden sonraki karakterleri almadı. İşte bu tarz sorun yaşamamak için "re.UNICODE" seçeneğini kullanacağız. Bu kullanım GNU/Linux ve Windows için biraz farklılık gösterir.
GNU/Linux işletim sistemi için;
# -*- coding: utf-8 -*-

import re
import locale
locale.setlocale(locale.LC_ALL,"")

liste = ["otobüs","otomobil","kamyon","minibüs"]

for i in liste:
    liste[liste.index(i)] = unicode(i,"utf8")

derle = re.compile("\w*",re.UNICODE)

for i in liste:
    print derle.search(i).group()
otobüs
otomobil
kamyon
minibüs
Gördüğünüz çıktılarımızı herhangi bir sorun olmadan aldık. Burada "import locale" ifadesinden sonrasına dikkat edin. İlk önce bir döngü içinde tüm liste elemanlarını Unicode dönüştürdük. Eğer bu dönüştürme işlemini yapmazsak yine istediğimiz çıktıyı alamayız. Ve derleme işlemi yaparken Türkçe karakterlerde sorun çıkmaması için "re.UNICODE" seçeneğini kullandık. Bu şekilde herhangi bir sorun olmadan çıktılarımızı doğru bir şekilde almış olduk.
Windows kullanıcıları için;
#-*-coding:cp1254-*-

import locale
locale.setlocale(locale.LC_ALL,"")

import re

liste = ["otobüs","otomobil","kamyon","minibüs"]

derle = re.compile("\w*",re.UNICODE)

for i in liste:
    print derle.search(i).group()
GNU/Linux ve Windows için kullanımlarda ufak farklılıklar bulunmakta. Bu farklılıklara dikkat etmemiz gerekir. Düzenli İfadeler ile Karakter Dizisi Değiştirme İşlemleri
Şimdiye kadar düzenli ifadelerde sürekli eşleştirme işlemleri yaptık. Düzenli ifadeler sadece bu işlem için kullanılmamaktadır. Düzenli ifadeler ile bir karakter dizisini değiştirmemizi de sağlar. Bu iş için temel olarak sub() ve subn() metotları kullanılır.
sub() Metodu
#-*-coding:utf8-*-

import re

metin = "Dünyanın en popüler sporu futbol'dur.Futbol çok eğlencelidir."

derle = re.compile("Futbol",re.I)

print derle.sub("Basketbol",metin)

Dünyanın en popüler sporu Basketbol'dur.Basketbol çok eğlencelidir.
En basit haliyle sub() metodunu kullanmış olduk. "Futbol" karakter dizilerini "Basketbol" ile değiştirmiş olduk. Daha önceden görmüş olduğumuz "re.I" seçeneği ile büyük,küçük harf uyumunu ortadan kaldırdık.
Not:sub() metodu karakter dizilerinde öğrendiğimiz replace() metoduna çok benzer. Fakat sub() metodu hem replace() metodundan daha güçlüdür hemde beraber kullanılabilen derleme seçenekleri ile daha esnektir. Ama tabi ki replace() metodu işimiz için yeterli ise onu kullanmalıyız.
subn() Metodu
subn() metodu sub() metodu ile neredeyse aynıdır. Tek fark olarak yapılan değişiklik sayısını da çıktı olarak vermesidir. Bu metot çıktı olarak iki ögeli bir demet vermektedir. Birinci öge değiştirilen metin ikinci öge ise yapılan değişiklik sayısıdır.
#-*-coding:utf8-*-

import re

metin = "Dünyanın en popüler sporu futbol'dur.Futbol çok eğlencelidir."

derle = re.compile("Futbol",re.I|re.U)

degistir = derle.subn("Basketbol",metin)

print "Metin üzerinden %s değişiklik yapılmıştır."%(degistir[1])

Metin üzerinden 2 değişiklik yapılmıştır.
Gördüğünüz gibi kaç değişiklik yaptığımıza rahat bir şekilde ulaşmış olduk.
Not:Düzenli ifadeler konusunu bitirdik. Bu konunun sonunda şunu söylemeliyiz ki, eğer yapmak istediğimiz işlemleri karakter dizileri metotları ile yapabiliyorsak, bu metotları kullanmalıyız. Çünkü karakter dizileri metotları hem daha hızlı hemde daha basittir.

1 yorum :

  1. Çok teşekkürler, metakarakterleri türkçe metinlerde de kullanabilmke oldukça işime yaradı.

    YanıtlaSil