3 Temmuz 2013 Çarşamba

Düzenli İfadeler - Metakarakterler

Düzenli ifadeler elle yapılması saatler alacak olan bir işlemi saliseler içinde yapmamızı sağlar.Düzenli ifadeler ile karakter dizileri üzerinde işlemler yapabiliriz.Burada hemen şunu da söyleyelim ki; eğer yapmak istediğimiz işlemi karakter dizileri metotları ile yapabiliyorsak kesinlikle bu metotları kullanmalıyız. Çünkü karakter dizileri metotları hem daha basit hemde çok daha hızlıdır.
Düzenli ifadeler Python programlama dilinin en zor konularından biridir. Ama öğrendikten sonra çok zor olan işlemleri çok basit bir şekilde yapmamızı sağlar. Zorluğundan dolayı kavrayabilmek için bol bol örnek çözülmesi gereken bir konudur.
Kullanım Yerleri
Nasıl yazıldığını tam olarak bilmediğimiz bir karakter dizisini aratabiliriz.
  • Örneğin; "congratulations" karakter dizisinin bulmak istiyor ve yazılışını tam olarak bilmiyorsak ilk ve son bir kaç karakterini verip aratabiliriz.
Bir metnin içindeki özel bir forma uyan parçaları bulabiliriz.
  • Örneğin; bir metin içindeki tüm URL'leri ana yapıyı tarif ederek ayıklayabiliriz.(http:// ile başlayan ve arada noktalar içeren kelimeler.)
Aldığımız verinin belli bir formata uygun olup olmadığını kontrol edebiliriz.
  • Örneğin; kullanıcıdan e-posta istediğimizde formatını kontrol edebiliriz. (@ içerecek ve ikinci blokta bir nokta bulunacak.)
Belli bir formatta aldığımız bir veriyi başka bir formatta dönüştürebiliriz.
  • Örneğin; Bir metin dosyasından aldığımız verileri kullanmak için Php dizisine dönüştürebiliriz.
Düzenli İfadelerin Metotları
Pythonda düzenli ifadeler ile ilgili her şey bir modül içinde tutulmaktadır. Bu modülün adı "re(regular expression)"dır. Tabi ki bu modülü kullanabilmemiz için ilk önce içe aktarmamız gerekir.
import re
Bu kod parçacığı ile modülü içe aktarmış olduk. Şimdi gelin bu modülün bize sunduğu tüm özellikleri listeleyelim.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

for i in dir(re):
    print i

DEBUG
DOTALL
I
IGNORECASE
L
LOCALE
M
MULTILINE
S
Scanner
T
TEMPLATE
U
UNICODE
VERBOSE
X
_MAXCACHE
__all__
__builtins__
__doc__
__file__
__name__
__package__
__version__
_alphanum
_cache
_cache_repl
_compile
_compile_repl
_expand
_pattern_type
_pickle
_subx
compile
copy_reg
error
escape
findall
finditer
match
purge
search
split
sre_compile
sre_parse
sub
subn
sys
template
Gördüğünüz gibi düzenli ifadeler bize bir çok metot/fonksiyon kullanma imkanı veriyor. Eğer herhangi bir metot/fonksiyon hakkında bilgi almak isterseniz. help(metot/fonksiyon adi) şeklinde kullanabilirsiniz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

print help(re.escape)

  Help on function escape in module re:

escape(pattern)
    Escape all non-alphanumeric characters in pattern.
Gelin şimdi biz bu metotlar içinde en sık kullanılanları açıklayalım.
Match() Metodu
match() metodu bir karakter dizisinin bizim aradığımız bir başka karakter dizisi ile başlayıp başlamadığını kontrol eder. Yani karakter dizisinin sadece en başına bakar.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

karakter = "python programlama dilini öğreniyorum."
print  re.match("python",karakter)
Düzenli ifade kalıpları match() metodunun ilk argümanıdır. İkinci argüman ise arama yapacağımız karakter dizisidir.Yukarıdaki kodları çalıştırdığınızda şu şekilde bir çıktı alacaksınız.
<_sre data-blogger-escaped-.sre_match="" data-blogger-escaped-0xb728e790="" data-blogger-escaped-at="" data-blogger-escaped-object="">
Bu ifade karakter dizisinin düzenli ifade ile eşleştiği anlamına gelir. match() metodu düzenli ifade ile karakter dizisinin eşleşip eşleşmediğini bize söyler. Eşleşti deyiş biçimi de bu şekildedir. Bu ifadeye Python'da "eşleşme nesnesi" denir.
print  re.match("delphi",karakter)
None
Burada eşleşme olmadığı için match() metodu geriye "None" ifadesi döndürdü. Yani match() metodu geriye eşleşme varsa "eşleşme nesnesi" yoksa "None" ifadesi döndürür.
En başta da söylediğimiz gibi match() metodu karakter dizisinin sadece en başına bakar.Gelin şu şekilde bir örnek verelim:
import re

karakter = "python programlama dilini öğreniyorum."
print  re.match("programlama",karakter)
None
"programlama" kelimesi karakter dizisi içinde bulunduğu halde "programlama" ile başlamadığı için match() metodu geriye "None" ifadesini döndürdü.
Biz bu yaptığımız işlemleri karakter dizisi metotları ile yapabilir miyiz?
karakter = "python programlama dilini öğreniyorum."
print karakter.split()[0]=="python"
True
print karakter.split()[0]=="programlama"
False
print karakter.startswith("python")
True
Bizim düzenli ifadelerden beklediğimiz sadece karakter dizisinin başlangıç ifadesini kontrol etmekse bunu karakter dizisi metotları ile yapmamız daha mantıklı olacaktır. Çünkü split() ve startswith() metotları match() metoduna göre hem daha basit hemde hızlıdır.
match() metodu bize bir eşleştirme nesnesi döndürüyor ve biz bulunan şeyi göremiyoruz. Eğer görmek istersek group() metodunu kullanabiliriz.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)
print kontrol.group()

python
Burada re.match("python",karakter) metodu ile dönen eşleştirme nesnesini bir değişkene atadık. Bu eşleştirme nesnesinin de kendi metotları bulunmaktadır.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)

for i in dir(kontrol):
    print i
__class__
__copy__
__deepcopy__
__delattr__
__doc__
__format__
__getattribute__
__hash__
__init__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
end
endpos
expand
group
groupdict
groups
lastgroup
lastindex
pos
re
regs
span
start
string
Listedeki metotlar eşleştirme nesnesi metotlarıdır. Dikkat ederseniz az önce kullandığımız group() metodu da listede bulunmaktadır.
Eğer eşleştirme nesnesi değilde geriye "None" ifadesi dönerse group() metodu hata verecektir.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("programlama",karakter)

print kontrol.group()

Traceback (most recent call last):
  File "/home/mazlumagar/workspace/Python/Duzenli İfadeler/match.py", line 9, in 
    print kontrol.group()
AttributeError: 'NoneType' object has no attribute 'group'
Bu hata mesajı programın çökmesine sebep olur. Bu yüzden kodlarımızı şu şekilde yazabiliriz.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)

if kontrol:
    print "Eşleşen kelime: " + kontrol.group()
else:
    print "Eşleşme başarısız."
search() Metodu
match() metodu karakter dizisinin sadece en başına bakıyor ve bir eşleştirme işlemi yapıyordu. search() metodu ise karakter dizisinin genelinde bir arama işlemi yapar.
import re
 
karakter = "python programlama dilini öğreniyorum."
print  re.match("programlama",karakter)
None
Bu örneği hatırlarsanız; match() metodu burada karakter dizisinin başında "programlama" ifadesini bulamadığı için "None" ifadesi döndürüyordu. Şimdi aynı örneği search() metodu ile yapalım.
import re
 
karakter = "python programlama dilini öğreniyorum."
print  re.search("programlama",karakter)

<_sre data-blogger-escaped-.sre_match="" data-blogger-escaped-0xb7239918="" data-blogger-escaped-at="" data-blogger-escaped-object="">
Gördüğünüz gibi search() metodu "programlama" ifadesini tüm karakter dizisinde aradı ve bulduğu için geriye "eşleşme nesnesi" döndürdü.
Not:match() metodunda bahsettiğimiz eşleşme nesneleri metodları search() metodu içinde geçerlidir.
Not:Düzenli ifadeler sadece karakter dizileri üzerinde işlem yapmamızı sağlar.Listeler, sözlükler gibi yapılar üzerinde doğrudan düzenli ifadeleri kullanamayız.
import re

liste = ["python","delphi","c++","c"]
re.search("python",liste)

Traceback (most recent call last):
  File "/home/mazlumagar/workspace/Python/deneme.py", line 6, in 
    re.search("python",liste)
  File "/usr/lib/python2.7/re.py", line 142, in search
    return _compile(pattern, flags).search(string)
TypeError: expected string or buffer
Gördüğünüz gibi program hata verdi. Listeler üzerinde işlem yapmak isterseniz şu şekilde bir kullanım yapabilirsiniz.
import re

liste = ["python","delphi","c++","c"]

for i in liste:
    arama = re.search("python",i)
    if arama:
        print arama.group()

python
findall() Metodu
findall() metodu karakter dizisi içinde aranan öğrenin hepsini bir liste şeklinde geriye döndürür.
import re

python ="""Python, nesne yönelimli, yorumlanabilen, birimsel (modüler) ve etkileşimli bir programlama dilidir.
Girintilere dayalı basit sözdizimi, dilin öğrenilmesini ve akılda kalmasını kolaylaştırır.Bu
da ona söz diziminin ayrıntıları ile vakit yitirmeden programlama yapılmaya başlanabilen bir dil olma özelliği kazandırır.
Modüler yapısı, sınıf dizgesini (sistem) ve her türlü veri alanı girişini destekler. Hemen hemen her türlü platformda çalışabilir.
(Unix , Linux, Mac, Windows, Amiga, Symbian). Python ile sistem programlama, kullanıcı arabirimi programlama, ağ programlama, uygulama ve veritabanı
yazılımı programlama gibi birçok alanda yazılım geliştirebilirsiniz. Büyük yazılımların hızlı bir şekilde prototiplerinin üretilmesi ve
denenmesi gerektiği durumlarda da C ya da C++ gibi dillere tercih edilir."""

print re.findall("Python",python);

['Python', 'Python']
Gördüğünüz gibi aradığımız "Python" kelimesi kaç tane varsa hepsini liste şeklinde geriye döndürdü. Programı şu hale de getirebiliriz.
kelime = raw_input("Aradığınız kelimeyi giriniz:")

print kelime + " karakter dizisinde " , len(re.findall(kelime,python)) , " kere geçmektedir."

Aradığınız kelimeyi giriniz:Python
Python karakter dizisinde  2  kere geçmektedir.
Metakarakterler
Şimdiye kadar kullandığımız düzenli ifadelerde, düzenli ifade ve karakter dizisi arasında doğrudan bir eşleşme yaptık. Bu yaptıklarımız düzenli ifadelerin en temel halidir. Yani "python" düzenli ifadesini karakter dizisinde bulmak için "python" kelimesini kullandık. "python" düzenli ifadesini doğrudan kendisi ile eşleştirmiş olduk. Peki bunları neden söylüyoruz ? Düzenli ifadelerden bu şekilde doğrudan eşleştirme yapmadan da arama yapmamızı sağlayan ifadeler vardır. Zaten düzenli ifadeleri özel kılan bu ifadelerdir.
Bu ifadelere Python'da metakarakterler denir. Aslında biz metakarakterleri daha önceden de kullanmıştık.
print "Python\nGeleceğin programlama dili"
Python
Geleceğin programlama dili
Bu örnekte gördüğünüz gibi Python "\n" ifadesini gördüğünde ekrana yazmak yerine yeni satıra geçmesi gerektiğini biliyor. Söylediğimiz gibi "\n" kendisiyle doğrudan eşleşmedi. Aynı şekilde "\t" ifadesini gördüğü zaman "tab" bırakması gerektiğini anlıyor.
print "Python\tGeleceğin programlama dili"
Python Geleceğin programlama dili
Düzenli ifadeleri düzenli ifade yapan bu metakarakterlerdir. Python bu karakterleri gördüğü zaman doğrudan eşleştirme yapmak yerine farklı tepkiler verecektir. Metakarakterler olmadan düzenli ifadeler ile çok faydalı işler yapmak mümkün değildir.
Python da bulunan metakarakterler:<\br> [ ] . * + ? { } ^ $ | ( )<\br> Şimdi gelin bu karakterleri sırası ile işlemeye başlayalım. Zaten açıkladıkça ne demek istediğimiz anlayacaksınız.
[ ](Köşeli Parantez)
[] metakarakterini açıklamaya çalışmak yerine gelin hemen örnek verelim.
liste = ["özcan demir", "mehmet", "süleyman",
         "selim", "kemal", "özkan nuri", "esra", "dündar",
         "esin", "esma", "özhan kamil", "özlem"]
Elimizde bu şekilde bir liste olsun. Biz daha önceden gördüğümüz yöntemler ile bu listeden bir öge bulmak istersek, örneğin "özkan", şu şekilde kullanmamız gerekir.
for i in liste:
    arama = re.search("özkan",i)
    if arama:
        print  arama.group()
özkan
Eğer arama yapmak istediğimiz öge birden fazla ise biz bu yaptığımızı hepsine tek tek uygulamamız gerekir. İşte tam bu nokta da [] metakarakteri yardımımıza koşuyor.
for i in liste:
    arama = re.search("öz[ckh]an",i)
    if arama:
      print  arama.group()
özcan
özkan
özhan
İşte sizinde gördüğünüz gibi tek tek hepsine uygulamak yerine değişen kısmı [] ifadesi içine aldık. Python köşeli parantez içinde gördüğü bütün karakterleri tek tek eşleştirme yapacağı karakter dizisine uyguluyor.İlk önce "öz" ile başlayan bütün ögeleri buluyor, ardından "c" harfi ile devam eden ve "an" ile biten ögeyi buluyor. Böylece "özcan" ifadesini bulmuş oldu. Bu yaptığı işlemi [] parantez içindeki bütün karakterlere sırasıyla uyguluyor.
Bu örnekte search() metodunu kullandığımıza dikkat edin. Şimdi gelin match() metodunu kullanarak yeni örnek yapalım.
import re

sifre = raw_input("Lütfen şifre oluşturun:")

if re.match("[0-9]",sifre):
    print "Şifre sayı ile başlayamaz."
else:
    print "Şifre başaarıyla oluşturuldu."
Lütfen şifre oluşturun:123sifre
Şifre sayı ile başlayamaz.
Gördüğünüz gibi kullanıcıdan bir şifre istedik ve bu şifrenin sayı ile başlaması durumunda kullanıcıyı uyardık. Burada [0-9] ifadesi sayıları temsil ediyor. Eğer rakam kontrolü yapmak isteseydik [a-z],[A-Z] şeklinde kullanabilirdik.Aynı örneği şu şekilde değiştirebiliriz.
import re

sifre = raw_input("Lütfen şifre oluşturun:")

if re.match("[0-9, ]",sifre):
    print "Şifre sayı veya boşluk ile başlayamaz."
else:
    print "Şifre başaarıyla oluşturuldu."
[] metakarakterini kullanırken bu örnekte olduğu gibi , ile ayırarak birden fazla kontrol yapabiliyoruz.Son olarak şu şekilde bir örnek verelim
import re

karakter ="TY76Z"

if re.match("[A-Z][A-Z][0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Aranılan ifade bulundu
Bu örnekte de ilk iki karakterin büyük harf ve onlardan sonra gelen karakterin ise sayı olmasını istediğimizi belirttik.
.(Nokta)
"." metakarakteri yeni satır hariç bütün karakterleri temsil etmek için kullanılır. [] metakarakterinde verdiğimiz örneği değiştirelim.
for i in liste:
    arama = re.search("öz.an",i)
    if arama:
      print  arama.group()
özcan
özkan
özhan
"." metakarakteri tek bir karakterin yerini tutar. Birden fazla karakteri temsil edemez.
import re

liste = ["ali","veli", "ahmet", "hasan"]

for i in liste:
    if re.match(".li",i):
        print i
ali
Bu örnekte gördüğünüz gibi geriye sadece "ali" ifadesi döndü. "." metakarakteri bir karakter temsil ettiği için "ali" ifadesini buldu. Fakat "Veli" ifadesinde iki karakter olduğu için bulamadı. Birden fazla karakterin yerini tutan metakarakteri daha sonra inceleyeceğiz.
import re

numara = raw_input("Okul numaranızı giriniz:")

if re.match(".[0-9][a-z][0-9,a-z]",numara):
    print "Okul numarası kabul edildi." 
else:
    print "Okul numarası formata uygun değil"  

Okul numaranızı giriniz:.8s7
Okul numarası kabul edildi.
Bu örnekte kullanıcıdan numara istedik ve gelin bu numaranın koşullarını sıralayalım:
  • İlk karakteri herhangi bir karakter olabilir.
  • İkinci karakteri sayı olmak zorunda.
  • Üçüncü karakteri küçük harf olmak zorunda.
  • Dördüncü karakteri sayı veya küçük harf olabilir.
*(Yıldız)
"*" metakarakteri düzenli ifadede konulduğu yerden bir önceki karakteri sıfır veya daha fazla sayıda eşitler. Tanımı biraz karışık ama örnek verince netleşecektir.
 #!/usr/bin/env python
# -*- coding: utf-8 -*-


import re

yildiz = ["kd","kod","kood","koood","boş"]
    
for i in yildiz: 
    if re.match("ko*d",i):   
        print i
kd
kod
kood
koood
Bu örnekteki çıktımızı incelerseniz sadece "*" metakarakterinden bir önceki karakterin adeti değişiyor. İşte sıfır ve daha fazla sayıda eşitler derken kastettiğimiz tam olarak buydu. "*" metakarakteri kendinden önceki sadece bir karakter ile ilgilenir. Yani burada sadece "o" karakterinin sıfır veya daha fazla sayıda bulunup bulunmadığını kontrol eder.
Burada yazdığımız düzenli ifade ile aradığımız ifadenin "k" ile başlamasını sonra sıfır veya daha fazla sayıda "o" ile davam etmesini ve "d" ile bitmesi gerektiğini söylüyoruz.
Şimdi gelin daha önceden öğrendiğimiz "." metakarakteri ile "*" metakarakterini birleştirelim ve bakalım ne olacak?
 #!/usr/bin/env python
# -*- coding: utf-8 -*-


import re

liste = ["Ahmet","Mehmet","Muhammet","Ali","Veli","Haşmet"]

for i in liste:
    if re.match(".*met",i):
        print i
Ahmet
Mehmet
Muhammet
Haşmet
Gördüğünüz gibi "met" ile biten bütün ögeleri listeledi. Hatırlarsanız "." bütün karakterleri temsil ediyordu. "*" ise kendinden önce gelen karakteri sıfır veya daha fazla sayıda eşitliyordu. Yani biz burada şu komutu verdik; bana karakter dizisi başında herhangi bir karakteri ("." ile) sıfır veya daha fazla sayıda içeren ve "met" ile biten ögeleri listele. Bu şekilde "met" ile biten kendisi de dahil olmak üzere her ögeyi listeler.
"*" sayesinde match() metodunu search() metodu gibi de kullanabiliriz. Daha önceden search() ile yaptığımız örneği şu hale getirelim.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match(".*programlama",karakter)

if kontrol:
    print "Aranılan öğe bulundu."
else:
    print "Aranılan öğe bulunamadı."
Aranılan öğe bulundu.
Not: Tabi ki search() metodunu kullanmak performans açısından çok daha iyidir.
+(Artı)
"+" metakarakteri "*" metakarakterine oldukça benzerdir. "*" kendisinden önceki sıfır veya daha fazla sayıda tekrar eden karakterleri ayıklıyordu."+" ise kendisinden önceki bir veya daha fazla sayıda tekrar eden karakteri ayıklar.
"*" metakarakterini işlerken verdiğimiz örneği hatırlarsanız, "kd" ögesini de çıktı olarak alıyorduk. Biz her zaman böyle olmasını istemeyebiliriz. Aradığımız karakterin öge içinde en az bir kere geçmesini istediğimiz durumlarda "*" yerine "+" metakarakterini kullanmalıyız.
import re

arti = ["kd","kod","kood","koood","boş"]
    
for i in arti: 
    if re.match("ko+d",i):   
        print i
kod
kood
koood
Gördüğünüz gibi bu sefer "kd" ögesi geriye dönmedi.
Hatırlarsanız [] metakarakterini işlerken şöyle bir örnek vermiştik.
import re
 
karakter ="TY76Z"
 
if re.match("[A-Z][A-Z][0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Burada aradığımız ifadenin ilk iki ögesinin büyük harf olmasını belirtmek için iki kere [A-Z] ifadesini kullandık. Ama şimdi "+" metakarakterini öğrendiğimize göre şu hale getirebiliriz.
import re
 
karakter ="TYS76Z"
 
if re.match("[A-Z]+[0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Aranılan ifade bulundu
İlk örneğimizde aranılan ifadenin ilk iki karakterinin büyük harf sonraki karakterin ise sayı olması gerekir. Ama "+" metakarakterini kullanarak yaptığımız örnekte bu sınırlama ortadan kalktı. Bir veya birden fazla sayıda büyük harf olabilir.
?(Soru İşareti)
Önceki bölümlerde işlediğimiz "*" metakarakteri eşleşmenin sıfır veya daha fazla olduğu durumlarda "+" metakarakteri ise eşleşmenin bir veya daha fazla olduğu durumlarda kullanılıyordu. "?" metakarakteri ise eşleşme sayısının sıfır veya bir olduğu durumlarda kullanılır.
Daha önce yaptığımız örneğin üç metakarakter ile kullanımını gösterelim ki aradaki farkı net bir biçimde görelim.
import re
yildiz = ["kd","kod","kood","koood","boş"]
    
for i in yildiz: 
    if re.match("ko*d",i):   
        print i
kd
kod
kood
koood

import re

arti = ["kd","kod","kood","koood","boş"]
    
for i in arti: 
    if re.match("ko+d",i):   
        print i
kod
kood
koood

import re

soru = ["kd","kod","kood","koood","boş"]
    
for i in soru: 
    if re.match("ko?d",i):   
        print i
kd
kod
Gördüğünüz gibi "?" çıktı olarak sıfır ve bir karakter barındıran "kd" ve "kod" ifadelerini geriye döndürdü.
{}(Küme Parantezi)
{} merakarakteri sayesinde bir eşleşmenin kaç adet olması gerektiğini belirtebiliyoruz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import re
 
kume = ["kd","kod","kood","koood","boş"]
     
for i in kume: 
    if re.match("ko{2}d",i):   
        print i
kood
Gördüğünüz gibi, biz küme parantezini kullanarak "o" karakterinin iki adet olmasını istediğimizi belirttik. Python da bize sadece "kood" ifadesini döndürdü.
{} küme parantezinin bir başka kullanım şekli ise; bir karakterin en az ve en çok kaç kere tekrar etmesi gerektiğini söyleyebiliyoruz. Hemen örneğine bakalım.
for i in yildiz: 
    if re.match("ko{0,2}d",i):   
        print i
kd
kod
kood
Bu sefer Python bize "o" karakterinin hiç olmadığı durumdan 2 adet olduğu duruma kadar geri döndürmüş oldu.
liste = ['23BH56','TY76Z','4Y7UZ','TYUDZ','34534','1agAY54']
   
for i in liste: 
    a=re.search("[A-Z].[0-9]",i)
    if a:   
        print a.group()
^(Şapka)
Hatırlarsanız daha önceki konularda match() ve search() metodlarını işlemiştik. match() metodu arama yaparken ifadenin sadece başına bakar search() metodu ise aranılan ifadeyi tüm öge içinde arardı.
^ metakarakteri ile ise search() motodu ile arama yaparken match() metodu gibi ifadenin sadece başına bakmasını istediğimizi belirtiyoruz.
import re
 
liste = ['23BH56','TY76Z','4Y7UZ','TYUDZ','34534','1agAY54']
   
for i in liste: 
    a=re.match("[A-Z]+[0-9]",i)
    if a:   
        print i
TY76Z 
Burada Python'a aradığı öge için şu koşulu belirttik; aradığın öge bir veya daha fazla sayıda büyük harf ile başlayacak ve onları bir sayı takip edecek. Python'da bu koşula göre bize çıktı verdi. Burada dikkat etmeniz gereken match() metodunu kullanmış olmamız. Şimdi aynı örneği search() metodu ile kullanalım.
for i in liste: 
    a=re.search("[A-Z]+[0-9]",i)
    if a:   
        print i 
23BH56
TY76Z
4Y7UZ
1agAY54
Gördüğünüz gibi çıktı sayımız bir hayli arttı. match() metodu eşleştirme yaparken ifadenin sadece başına bakıyor search() metodu ise tüm ifade içinde eşleştirme yapıyordu. Şimdi aynı örnekte search() metodunu "^" metakarakteri ile beraber kullanalım.
for i in liste: 
    a=re.search("^[A-Z]+[0-9]",i)
    if a:   
        print i 
TY76Z
Gördüğünüz gibi search() metodundaki çıktının aynısını aldık. Biz burada yazdırma işlemi yaparken listenin elemanını yazdırıyoruz. Şu şekilde eşleştirme nesnesi ile dönen ifadeyi yazdıralım.
for i in liste: 
    a=re.search("[A-Z]+[0-9]",i)
    if a:   
        print a.group()
BH5
TY7
Y7
AY5
Bu sefer bize sadece aradığımız ögeyi geriye döndürdü. Eğer biz burada tüm ifadeyi döndürmesini istersek şu şekilde kullanabiliriz.
for i in liste: 
    a=re.search(".*[A-Z]+[0-9].*",i)
    if a:   
        print a.group()
23BH56
TY76Z
4Y7UZ
1agAY54
Gördüğünüz gibi tüm ifadeyi geriye döndürmüş olduk.
"^" metakarakterinin bir görevi daha vardır. Hariç anlamında da kullanılır. Yani arama işlemi yaparken belli bir koşula uyan ifadeleri almak istemeyebiliriz. Bu durumlarda da "^" metakarakterini kullanabiliriz.
for i in liste:
    nesne = re.match("[0-9A-Z][^0-9]",i)
    if nesne:
        print i
4Y7UZ
TYUDZ
1agAY54
Burada ifadenin harf veya sayı ile başlamasını ondan sonra ise sayı gelmemesini söyledik. Python da bize ona göre çıktı vermiş oldu.
$(Dolar)
"$" metakarakteri bir önceki bölümde incelediğimiz "^" metakarakterinin tam tersi işi yapar. "^" karakteri ile karakter dizilerinin nasıl başlayacağını belirtiyorduk. "$" metakarakteri ile de nasıl biteceğini belirtiyoruz.
Elimizde şu şekilde bir isim listesi olsun ve biz bu listeden ismi "an" ile bitenleri ayıklayalım.
liste = ['Hasan','ayşe','ahmet','Alkan','esra','Alıngan','Altan','veli']
   
for i in liste:
    if  re.search('an$',i):
        print i      
Hasan
Alkan
Alıngan
Altan
Gördüğünüz gibi çıktılar tamda beklediğimiz gibi oldu.
Not: Burada önemli olan "^" ve "$" metakarakterlerini search() metodu ile kullanmanız gerektiğidir. Eğer match() metodu ile kullanırsanız herhangi bir çıktı alamazsınız.
Ters Bölü
"\" işareti daha önceden de bildiğimiz kaçış dizisidir. Şimdiye kadar işlediğimiz metakarakterler kendileri ile eşleşmiyorlar. Yani bu metakarakterleri bir karakter dizisinde aramak istesek özel anlamları yüzünden bu mümkün olmayacaktır. İşte bu özel anlamlarını iptal edip bu karakterleri Python'a normak karakter gibi göstermek için "\" kaçış dizisini kullanıyoruz.
import re
 
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+/',i):
        print i   
4/2
Örneği açıklayalım. Biz burada Python'a aradığın öge sayı ile başlayacak, bu sayı bir veya daha fazla sayıda olabilir(+ metakarakteri) ve sonra / (Buradaki normal bölü işaretidir.) devam edecektir. Python da bu koşula uyan tek karakter dizisini bize döndürdü. Dikkat ederseniz buradaki "+" karakteri metakarakterdir yani özel bir anlamı vardır. Kendisinden önceki sayının bir veya daha fazla sayıda olabileceğini belirtiyor. Ama biz liste içinde sadece toplama (+) işlemi olan ögeleri getirmek isteseydik ne yapmamız gerekiyordu ? Örneğimize bakalım.
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+\+',i):
        print i       
2+5
6+9
7+5
Gördüğünüz gibi sadece toplama işlemi olan ögeleri ayıkladık. "\" işareti ile kendisinden sonra gelen "+" metakarakterinin özel anlamını elinden almış olduk. Yani sıradan bir karakter haline getirdik. Burada kullandığımız işaretin bölü(/) işareti olmadığına dikkat edin. Eğer bölü işaretini kullanırsanız ilk ifadedeki çıktıyı elde ederiz.
for i in liste:
    if  re.match('[0-9]+/+',i):
        print i 
4/2
Burada "+" metakarakteri özel anlamını yitirmedi. Yani biz bir veya daha fazla sayıda bölü (/) işareti ara demiş olduk.
|(Dik Çizgi)
"|" metakarakteri "veya" anlamına gelir. Birden fazla eşleştirme kalıbı kullanılmak istenen durumlarda kullanılır.
Bir önceki başlıkta verdiğimiz örnek üzerinden gidelim.
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+\*|[0-9]+\-',i):
        print i      
3*4
5-2
Bu örnekte gördüğünüz gibi iki ifadenin kalıbını "|" metakarakteri ile ayrı ayrı oluşturduk. Python da ikisine birden uyanı bize getirdi. Burada "\" kaçış dizisini kullanarak ilk önce sayı ile başlayan ve "*" ile devam edenleri veya sayı ile başlayan "-" ile devam edenleri getir demiş olduk.
Elimizdeki bir listede herhangi bir ögenin kendisini yazıyorsak da bu metakarakteri kullanabiliriz.
re.search("Galatasaray" | "Fenerbahçe" | "Beşiktaş")
() (Parantez)
"()" metakarakteri düzenli ifade kalıplarını gruplamamızı sağlar. Bu metakarakter sayesinde bir karakter dizisinin istediğimiz bölümlerini çok rahat bir şekilde ayıklayabiliriz.
İleride eşleşme nesneleri metotlarından group() metodunu işlerken örnekler vereceğiz.

3 yorum :

  1. Bunların hepsini çok iyi bilmek gerekiyor mu işe lazım oldukça bakılabilir gibi geldi.Yoksa çok fazla akılda kalmaz.

    YanıtlaSil
  2. Faydalı bir paylaşım çok teşekkürler..

    YanıtlaSil