Perl dilinin güçlü yanlarından biri de Regular Expressionlar.
Diğer programlama dillerinde çok sayıda kodla yapabileceğimiz işler perlde bu yöntemi kullanarak tek satırda bile halledilebiliyor.
Anlaşılır olması için örnekler vermeye çalıştım.
Örnekleri uygulamak için sisteminize Perl ve bir perl editör programı indirip kurun. Tavsiyem Perl Builder programı.
Detaylı bilgi için Perlde düzenli ifadeler genelde iki / işareti arasında olur. /def/ ifadesi sedefler kelimesinde aratıldığında sonuç True yani Doğru olacaktır. split fonksiyonu ile düzenli ifadeleri kullanabilir ve bir metni parçalara ayırabiliriz.
$metin = "Perl öğrenmek sanıldığı kadar zor değil"; @parcalar = split(/ /,$metin);üstteki kodlar $metin değişkenindeki metni boşluklardan ayırırarak @parçalar boyutlu değişkenine aktarır. Dikkat: İki bölü arasında bir boşluk var
~ operatörü
~ operatörüyle metin içinde düzenli ifadeye uygun kelime olup olmadığı araştırılır.$sonuc = $degisken =~ /abc/;=~ operatörüyle $sonuç değişkenine kelime varsa, True yada 0 olmayan bir değer ; kelime yoksa, False ya da 0 değeri atanır.
$sonuc = $degisken !~ /abc/;!~ operatörü metin içinde aranılan olmadığını tespit eder. Yoksa 1, varsa 0 sonucu alırız. Yani ilk kodun tersi.
$istek = "Bir çay istiyorum. Lütfen"; if ($istek =~ /Lütfen/){ print "Nezaketinize teşekkürler";} else { print "Nazik değilsiniz.";}
Düzenli İfadelerde Özel karakterler.
+ karakteri
Bir ya da daha fazla karakter olup olmadığını araştırır./Bi+r/
ifadesine uyan birkaç kelime : Bir Biir Biiiiiiiir
@kelimeler = split (/ /, $metin);koduyla metini boşluk karakterlerinden bölerek kelimelere ayırmayı öğrenmiştik. Metinde fazladan konmuş boşluklar varsa kelime sayısı artacaktır
Bu metinde fazladan gereksiz boşluklar var.metni boşluklarda kelimelere ayrıldığında
("Bu","","metinde","fazladan","","gereksiz","boşluklar","var.")sonucunu elde ederiz. Bunu önlemek için
@kelimeler = split (/ +/, $metin);kodunu uygulayabiliriz. Böylece fazladan konulmuş boşluklar dikkate alınmayacak onlar 1 taneymiş gibi değerlendirilecek.
("Bu","metinde","fazladan","gereksiz","boşluklar","var.")Metindeki kelimelerin sayısını veren bir kod örneği:
$metin = "Bu metinde fazladan gereksiz boşluklar var."; @kelimeler = split(/ +/,$metin); $kelimesay = @kelimeler; print "Metinde $kelimesay kelime var.";
[ ] karakterleri
Alternatif karakterler grubu oluşturmak için kullanılır./a[bB]c/üstteki ifadeye uygun kelime : abc veya aBc olacaktır
/A[0123456789]/buna uygun olanlar ilk harfi A diğer harfi bir sayı olan kelimeler olacaktır.
/a[123]+b/buradaki artı işareti grup içindekilerden birinin 1 ya da daha fazla tekrarını ifade eder. uygun kelimeler
a1111b 12b a333bTab karakteri \t ve boşluk dan metni ayırmak için kullanılacak kod.
@kelimeler = split(/[\t ]+/, $metin);
* ve ? karakterleri
+ işareti 1 ya da daha fazla tekrarı ifade ediyordu. * ise 0 ya da daha fazla tekrarı ifade eder. yani hiç yoksa bile kabul edilir./ab*c/bu koda uyan kelimeler : ab abc abbbc ...
/a[123]*b/ise : ab , a1b , a222b , a3b ...
? karakteri ise belirtilen karakterin 0 ya da 1 defa olduğunu araştırır.
/ab?c/ise : ac , abc olabilir ama abbc olamaz.
İfadelerde özel karekterleri kullanma
Evet *+?[] gibi özel karakterlerle arama ifademizi belirtiyoruz. Peki örneğin * karakterini arattırmak istersek ne yapacağız? Çünkü diğer karakterler gibi kullanacak olsak başka şeyi ifade eder. Bu tür karakterleri belirtmek için başına ters bölü işareti konur. \ işareti perl e ardından özel bir karakterin geldiğini söyler. Örnek
/a\*+b/ise: a*b a***b ...
Akla şöyle bir soru gelebilir \ işaretini aratmak istersem? diye. Bunun için de aynı yöntemi kullanırız.
/a\\b/ise: a\b
Eğer Perl5 kurulu ise özel karakterleri girmek için \Q ve \E karakterlerini de kullanabilirsiniz. \Q özel karakter tanımlama başlangıcını, \E de sonunu bildirir.
/\Q^ab*/ise : ^ab*
/\Q^ab\E*/ise: ^a ile başlayan 0 ya da daha fazla b den oluşur.
Herhangi bir rakam ya da harf
/a[0123456789]b/böyle bir kodu daha önceden öğrenmiştik. a ile başlayıp ardından bir rakam ve ardından b. Bunu ifade etmemin birbaşka yolu
/a[0-9]b/dir. [0-9] ifadesi 0 dan 9 a kadar rakamlardan herhangi biri demektir. Aynı şekilde
[a-z] ile küçük harfleri, [A-Z] ile de büyük harfleri ifade ederiz. Dikkat Yalnızca İngilizce harfler geçerlidir.
/[a-z][a-z]/küçük harfli, 2 harfli herhangi bir kelimeyi ifade eder.
/[0-9a-zA-Z]/bir karakterlik büyük ya da küçük harf yada rakamdan oluşur.
/\$[A-Za-z][_0-9a-zA-Z]*/ifadesi perlde değişken tanımını ifade eder. $ ile başlar 2. karakter bir harf olmak zorunda, sonraki gelenler ise _ , rakam ya da harften 0 ya daha fazla.
^ ve $ karakterleri
Aradığımız satırın başlangıç ve bitiş kısımlarını ifade etmek için kullanılır. ^ başlangıç, $ bitiş karakteri tanımlaması içindir/^abc/abc ile başlayan satırı ifade eder.
/dir$/sonu dir ile biten satırı tarif eder.
/^bugün$/yalnızca bugün kelimesini ifade eder.
daha önceki perl değişken tanımlaması yetersiz kalmıştı şimdi
/^\$[A-Za-z][_0-9a-zA-Z]*$/ile başlangıç ve bitiş karakterlerini sabitlemiş oluk.
\b ve \B karakterleri
Kelime sınırlarını ve içini tanımlamak için kullanılır/\bgöz/göz ile başlayan kelimeleri ifade eder. göz , gözlük gözlükçü gibi. sugözü kelimesinde bu ifadeyle aratacak olursak olmadığını söyler.
\b yi kelimenin sonunu tanımlamak için de kullanabiliriz.
/göz\b/göz ile biten kelimeler. paragöz , açıkgöz, karagöz gibi.
/\bgöz\b/yalnızca göz kelimesini ifade eder.
\B karakteri ise kelimenin bulunduğu yerin kelime içi olduğunu gösterir kelime başı ve sonu değil. \b nin tersi.
/\Bgöz/karagöz , elagöz ... yalnız göz olamaz.
/göz\B/gözlük , gözlükçü , gözcü ... yalnız göz olamaz.
/\Bgöz\B/içinde göz geçen kelimeler: karagözcü , elagözlü ...gibi. göz , gözcü , akgöz gibi kelimeler kabul edilmez.
Örnek:
$metin = "sen seni bil, sen seni, sen seni bilmezsen, patlatırlar enseni"; @kelimeler = split(/ /,$metin); foreach $klm (@kelimeler){ if ($klm =~ /\bsen/){ $say1++; } if ($klm =~ /sen/){ $say2++; } } print "sen ile başlayan $say1 kelime var.\n"; print "içinde sen olan $say2 kelime var.";Sonuç:
sen ile başlayan 6 kelime var. içinde sen olan 8 kelime var.
Alternatiflerin dışındakiler
/g[üö]z/ifadesi göz veya güz kelimelerini ifade eder
/g[^üö]z/ifadesinde ise alternatif harfler olan ü ve ö nün dışındakileri tamsil eder. Yani 1. harfi g , 2. harfi ü ve ö nün dışında birşey 3. harf ise z.
Karakter aralığı
/[0-9]/ un herhangi bir rakama denk geldiğini öğrenmiştik bunu yerine /\d/ kullanacak olursak aynı işi görür.Karakter aralığı tablosu
İfade | Tanımlama | Aralık |
\d | Bir rakam | [0-9] |
\D | Rakam dışında bir karakter | [^0-9] |
\w | Kelime oluşturan karakterler | [_0-9a-zA-Z] |
\W | Kelime oluşturmayanlar | [^_0-9a-zA-Z] |
\s | Herhangi boşluk: Satır sonu, satır atla, tab gibi | [ \r\t\n\f] |
\S | Boşluklar dışında kalanlar | [^ \r\t\n\f] |
/[\da-z]/herhangi bir rakam ya da küçük harf
Herhangi bir karakter
(.) nokta karakteri enter karakteri hariç herhangi bir karakteri ifade eder./a.c/a ile başlayıp c ile biten 3 karakterli kelimeleri ifade eder.
/a.*c/a ile başlayıp c ile biten herhangi bir yazı.
/C.*l.*t.*ık/ifadesine uygun bir kelime : Cebelitarık
Olanların sayısı
+ ile 1 yada daha fazlasını, ? ile de 0 ya da 1 tanesini ifade ediyorduk. Bazen tekrar edenin kaç tane olduğunu belirlemek gerekebilir. Bunu { ve } karakterleri arasında bir rakam ile belirleriz./ab{1,3}c/ile abc abbc abbbc kelimelerine uyan bir ifade yazmış olduk. ab abbbbc kelimeleri buna uymayacaktır. Yani b nin1 den 3 e kadar tekrarını tarif ettik.
/ab{3}c/yalnızca abbbc yi tarif eder.
/ab{3,}c/b için alt tekrar sınırı 3 , üstsınır verilmemiş. a ile başlayan En az 3 b ile devam edip c ile biten manasında.
/a{0,3}c/
a ile başlar b 3 den fazla değil ve c
/[a-z]{1,3}/1 , 2 ya da 3 harfli kelime
/.{3}/herhangi 3 karakterden oluşan kelime
Seçenek belirleme
| karakteri ile 1 ya da daha fazla seçenek belirlenebilir./ali|veli/ali ya da veli den biri
/[a-z]+[0-9]+/1 veya daha fazla küçük harf veya 1 ya da daha fazla rakam
Hafızaya alma
Örneğin şu şekilde bir ifade kullanmak istiyoruz;1 ya da daha fazla rakam ya da küçük harf : [\da-z]+
sonra noktalı virgül ya da iki nokta [;:]
sonra yine 1 ya da daha fazla rakam ya da küçük harf [\da-z]+
sonra noktalı virgül ya da iki nokta [;:]
sonra yine 1 ya da daha fazla rakam ya da küçük harf [\da-z]+
Şimdi kodları birleştirelim
/[\da-z]+[:;][\da-z]+[:;][\da-z]+/Gördüğünüz gibi tekrar eden ifadeler var. Perlde tekrar eden ifadeler için bir kolaylık var.
İfade parantez içine alınır.
([\da-z]+)perl parantez içi ifadeyi hafızaya alır. İfade içinde bunu tekrar kullanmak istersek \n kullanarak çağırırız. n yerine hafızaya alınmış ifadelerden kaçıncısı olduğunu yazarız.
/([\da-z]+])[:;]\1[:;]\1/perl \1 kodunu gördüğü yere hafızaya alınmış [\da-z]+ kodlarını ekleyecektir. Diğer tekrar edene de aynı yöntemi uygulayacak olursak
/([\da-z]+)([:;])\1\2\1/Gördüğünüz gibi hem kod kısaldı hem de karmaşadan kurtuldu. Tarih formatında (29-06-01 gibi) bir text aratmak istersek
/(\d{2})([/-:\.])\1\2\1/kullanabiliriz. Yalnız dikkat 28-06:01 gibi yazılmış bir kodu da bulacaktır.
Hafızadaki ifadenin sonucu değişkene
İfadeyi parantez içine alarak hafızaya alabiliyoruz fakat bunu başka bir komut satırında \1 kullanarak ifade edemeyiz/-?(\d+)\.?(\d+)/ile küsurlu sayı arattırabiliriz. başka bir satırda
/\1/kullanmak doğru olmayacaktır. Hafızadaki ifadenin sonucunu nasıl alırız?. Perl in dahili değişkenleri vardır $1 $2 ... gibi $1 ilk hafızaya alınmış ifadenin sonucunu tutar, $2 sonraki ... gibi. Metin içinde geçen küsurlu sayının tam sayısını ve küsuratını alan kod
$metin = "Bu metinde 23.415 sayısı var"; $metin =~ /-?(\d+)\.?(\d+)/; print "Tam sayı : $1\n"; print "Küsuratı : $2";$1 $2 nin değerleri yeni bir ifade kullanılana kadar hafızada kalır. Yeni bir ifade kullanıldığında bu değerler kaybedilir. kaybetmek istemezseniz başka bir değişkene aktarabilirsiniz
Html kod içinden sayfa başlığı metnini alan kod
$htmkod = "<html><head><title>Perl hakkında</title></head></html>"; $htmkod =~ /<title>(.*)<\/title>/; print "Başlık = $1";Diğer bir Perl dahili değişkeni de $& dır. Bu, son ifadenin sonucunu hafızada tutar
$metin = "Bu metinde -45.15 sayısı var"; $metin =~ /-?(\d+)\.?(\d+)/; print "Sayı = $&";
Özel karakterlerin öncelik sırası
Nasıl bir matematiksel işlemde * ve / öncelikli olarak işleme konursa perl ifadelerinde de özel karakterlerin öncelik sırası vardır. Aşağıdaki tablo öncelik sırasını verirÖzel karakter | Tanımı |
() | Hafızaya alma |
+ * ? {} | Tekrar etme |
^ $ \b \B | Başlangıç, bitiş |
Alternatifler |
İfadeyi sınırlayan karakteri belirleme
ifademizi sınırlamak için / işareti kullanıyoruz. İfademizin içinde /usr/local/webpages/mesut/web geçecekse aynen kullanamayız çünkü / özel bir karakter. Bunu/\/usr\/local\/webpages\/mesut\/web/olarak yazabiliriz. Ancak hem kod artıyor hemde okunurluk zorlaşıyor. Perlde buna da bir çare getirmişler sınırlayan karakteri m ile kendimiz belirleyebiliyoruz
/abc/yerine
m!abc!kullanabiliriz. çünkü m nin ardından sınırlama karakterini ! olarak belirledik Eğer ifade içinde sınırlama karakteri kullanacaksak \ ile beraber kullanmalıyız.
m!ab!cd!yanlış olacaktır. Yerine
m!ab\!cd!yazabiliriz. Şimdi
m!/usr/local/webpages/mesut/web!ile daha anlaşılır bir kod oldu.
Düzenli İfade Seçenekleri
İfade seçenkleri bir harf ile belirtilir ve son sınır karakterinden sonra kullanılır. Örnek/a[bc]d/iSeçenekler tablosu
Seçenek | Açıklama |
g | Geçerli tüm veriler |
i | Büyük/küçük harf ayırımı yapma |
m | Metnin çok satırdan olduğunu varsay |
o | Yalnız bir defa |
s | Tek satırmış gibi değerlendir |
x | Boşlukları yoksay(dikkate alma) |
g seçeneği
Veride ifadeye uyan tüm veri parçalarını alır. Örnek/.a/gmetinden 1. harfi herhangi bir harf 2. harfi a olanları arar
@parcalar = "salata" =~ /.a/g; foreach $p (@parcalar){ print "$p\n<br>"; }başka bir örnek
while ("kelebek" =~ /.e/g){ $m = $&; print ("$m\n"); }
Aramaya başlanacak yeri belirleme
pos komutu ile metnin belli bir kısmından itibaren arama yaptırabiliriz. Kullanımıpos($metin) = arama pozisyonu;
Örnek:
$metin = "kelebek ve melemen"; pos($metin) = 7; while ($metin =~ /.e/g){ $parca = $&; print ("$parca\n"); }
Sonuç:
ve me le meolacaktır. 7. karakterden itibaren aradığı için kelebek kelimesi dikkate alınmadı. Dikkat : ilk karakter 0 olarak alınır. pos komutu Perl4 de yoktur.
i seçeneği
Metin içinde arama yapılırken büyük/küçük harf ayırımı yapılmaz./ab/iAb ab aB AB bu tanıma uygundur
m seçeneği
metnin çok satırdan oluştuğunu belirtir. Bu seçenek yalnız Perl5 de kullanılabilir. Örnek:$metin = "Güzel Bir Gün. \nBir gün..."; print "Bir ile başlayan satır "; if ($metin =~ /^Bir/m) {print "var";}else{print "yok";}Yukardaki kodda m harfini silerek yada metin içindeki \n i silerek deneyin. \n yeni satır başlangıcını belirtir.
x seçeneği
Perl5 de kullanılabilir. ifadedeki boşlukları dikkate almaz/\a [bc] \d AD/xifadesi
/\a[bc]\dAD/xgibi değerlendirilir
Yerine koyma operatörü
Bir metindeki belirtilen ifadeye uyanları başka bir şeyle değiştirmek için kullanılır.s/arama ifadesi/yerine konacak/
Örnek
$metin = "Ali Ve Veli"; $metin =~ s/Ve/de/g; print $metin;
Sonuç : Ali de deli Çünkü Bulunan ve lerin de ile değişmesini istedik. g seçeneği tüm bulunanları değiştir. Daha önceki öğrendiğimiz ifade kuralları burada da geçerlidir.
$metin = "AAli Veeee Veli"; $metin =~ s/[ae]+/,/ig; print $metin;
kodlarını çalıştırın neyi değiştirdiğini inceleyin.
Yerine koyma operatörü seçenekleri
Seçenek | Açıklama |
g | Bulunanların tümünü değiştir |
i | Büyük / küçük ayrımı yok |
e | İfadenin değerini alıp değiştir |
m | Çoklu satır |
o | Yalnız bir kere |
s | Tek satır |
x | İfadede boş karakterleri önemseme |
$metin = "Bu metin\nçok satırdan\noluşuyor"; $metin =~ s/\n/ /g;üstteki kodlar metindeki \n leri boşluk ile değiştirir. Böylece çok satırlı metin tek satırlı olur
$metin = "Bu \r\r metin\n\n\n çok satırdan\n oluşuyor ve gereksiz boşluklar var"; $metin =~ s/[\n\r\t ]+/ /g; print $metin;üstteki kodlar metindeki 1 veya daha fazla \r \n \t ve boşluğu tek boşluk ile değiştirir. \n = yeni satır, \r satır atla, \t tab karakteridir.
s/\.//güstteki kod metindeki noktaları siler. // ile yerine birşey koyma demek istedik. Yani sil.
$sayi = "105"; $sayi =~s/(\d)/$1*5+1/eg; print $sayi;e seçeneği, yerine konacak olanın önce hesaplanıp değerinin yerine konacağını belirtir. Kodları inceleyelim (\d) ile herhangi bir rakam diyoruz ve parantez içine alarak hafızaya almasını istiyoruz $1*5+1 ile de bulunan sayıyı 5 ile çarp 1 ekle sonra bulduğun ile değiştir diyoruz. ilk bulduğu rakam 1. Bunu 5 ile çarpıp 1 ilave edince 6 2. rakam 0. Bunu 5 ile çarpıp 1 ilave edince 1 3. rakam 5. Bunu 5 ile çarpıp 1 ilave edince 26 Sonuç: 6126
/ nün yerine farklı bir ifade sınırlayıcı belirleyebilirsiniz.
s%ab/cde%123/45%g;
ab/cde yi 123/45 ile değiştir dedik. sınırlayıcı karakter %
Çeviri operatörü
Bir grup karakterin başka bir grup ile değiştirmesi için kullanılır. Kullanımıtr/grupkarakterler/yerine konacak grupkarakterler/
Örnek:
$metin = "Dağ başını duman almış. Çöl rüzgarı"; $metin =~ tr/ğşıöü/gsiou/; print $metin;Metindeki ingilizcede olmayan karakterler benzerleriyle değiştirilir.
tr/[A-Z]/[a-z]/Tüm büyük harfler küçükleriyle değiştirilir. Dikkat İngilizcede olmayan karakterleri dikkate almaz.
Dikkate alması için
tr/[A-Z]ÜĞİŞÇÖ/[a-z]üğişçö/
Çeviri operatörü seçenekleri
Seçenek | Açıklama |
c | Belirtilmeyen tüm karakterler değiştirilir |
d | Belirtilen tüm karakterleri sil |
s | Çok sayıdaki karakter tanımlandı ise hepsini 1 karakterle değiştirir |
tr/A-Z/ /cbüyük harfler hariç hepsini boşluk ile değiştirir
tr/a-z/ /dküçük harfleri siler
tr/ÜĞİŞÇÖ/?/sBüyük harfli Türkçe karakterleri soru işareti ile değiştirir.
BÜYÜK -> B?Y?K olur DÜĞÜN -> D?N olur. Çünkü ÜĞÜ tek bir karakterle değiştirilir.
Birkaç Örnek:
s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg% ile başlayan ([a-fA-F0-9][a-fA-F0-9]) a dan f ye kadar veya A dan Z ye kadar veya 0 dan 9 a kar olan 2 karakter ve bunu hafızaya al. pack("C", hex($1)) pack komutu verilen sayıyı değişik formatlara dönüştürür. Burada, verilen 16 lık sayıyı karaktere dönüştürür. Seçenek olarak e kullanıldığına dikkat edin. e ifadede bir işlem var ise onun yapılıp da değişikliğin yapılacağını belirtir.
Bu kod tahmin edeceğiniz gibi formdan gönderilen 7 bitlik verileri 8 bite dönüştürür. Örneğin formda ş yazdığımızda bu bilgi 8 bitlik olduğundan ascii karakter kodu hex olarak gönderilir. Diğer karakterlerden ayırmak için de başına % işareti konur. Yani ş karakteri %FE ye dönüşür. Bu da üstteki perl kodu ile tekrar ş ye dönüştürülür.
2. örnek:
if ($email !~ /\w+@\w+\.\w\w+/){$email="";}email adresi doğru formatta yazılmamışsa $email değişkeni sıfırlanır \w ifadesi [_0-9a-zA-Z] e denk gelir.
3. örnek:
if ($fweb !~ /^(fht)tp:\/\/\w+\.\w\w+/){$fweb = "";}web adresi formata uygun değilse kabul etmez.
4. örnek
if ($metin =~ /\S{41,}/g){print "metinde 40 karakterden uzun kelime var";}formda yazılmış anlamsız kelimeler giren olursa uyarmanız için.
Hiç yorum yok:
Yorum Gönder