Ana Sayfa | Eğitim Cd'leri | Eğitim Kitapları |  212 428 23 21-23 39


 

 

PERL'E DERSLERİ - 4

Perl dili öncelikle dosya taramalari yapmak üzere gelistirildi. Bir önceki bölümde dosyalarla nasil calisabilecegimizi ögrendik. Perl'ün yetenekleri bununla sinirli degil. Perl ve diger dillerde regüler terim olarak isimlendirilen harf ve kelime gruplariyla bir metni taramamiz mümkündür.
Bu bölümde regüler terimleri inceleyecegiz. Bu terimleri kullanarak, dosyalar üzerinde ne kadar kolay tarama yapabileceginizi göreceksiniz. Regüler terimler dogru kullanildigi taktirde, isimizi kolaylastiracak cok kuvvetli araclardir. Dilerseniz artik regüler terimlerle tanisalim.
Regüler terimler, bir dosyanin icinde gecen kelime ve kelime gruplarini bulmak icin kullanilir. Asagidaki örnegi inceleyelim:

$var="Bugün hava cok güzel. Arkadaslarla sinemaya gidecegiz.";
if($var = ~ /cok/)
{
print "Cok kelimesi kullaniliyor\n";
}


$var degiskeni bir string ihtiva ediyor. If döngüsünü kullanarak, cok kelimesinin string icinde kullanilip, kullanilmadigini kontrol ediyoruz. /cok/ burada kullanilan regüler terimdir. Regüler terimler iki / / isareti arasinda yer alir. Eger aradigimiz regüler terim $var stringi icinde yer aliyorsa, ekranda "Cok kelimesi kullaniliyor" mesajini görecegiz.
Bazen icinde aradiginiz regüler terimin bulunmadigi bir dosyayi taramak isteyebilirsiniz. Bu is icin asagidaki örnegi kullanabilirsiniz: NOT (!) operatörünü kullanarak, regüler terimin string icinde bulunmamasi gerektigini belirtiyoruz. If döngüsü, string icinde aradigimiz regüler terimin olmamasi durumunda print komutunu calistiracaktir.

$var="Bugün hava cok güzel. Arkadaslarla sinemaya gidecegiz.";
if($var !~ /Tiyatro/)
{
print "Tiyatro kelimesi kullanilmiyor\n";
}


Tarama yaparken regüler terime opsiyonlar (flags) verebiliriz. Kullandigimiz opsiyona göre, regüler terimin, tarama sürecinde davranisi degisik olacaktir.
Tarama yaparken büyük/kücük harf ayrimi yapmak istemiyorsaniz, i opsinonunu kullanin.

$var="Bugün hava cok güzel. Arkadaslarla sinemaya gidecegiz.";
if($var= ~/Cok/i)
{
print "Aradiginiz kelime mevcut.\n";
}


Genelde regüler terim taramalari ilk satir üzerinde yapilir. $var degiskeni icindeki string birden fazla satirdan olussaydi, yukarda yer alan programlar, diger satirlarda belki yer alabilecek regüler terimi bulamiyacaklardi. Tüm satirlarda tarama yapmak icin m opsiyonunu kullanabilirsiniz.

$var=" Bugün hava cok güzel.\n Arkadaslarla sinemaya gidecegiz.\n Cok güzel bir gün olacak\n";
if($var= ~/cok/im)
{
print "Aradiginiz kelime mevcut.\n";
}


S opsiyonunu kullanarak, satir icinde bulunan regüler terimi baska bir kelimeyle degistirmeniz mümkün. Asagida yer alan örnekte cok kelimesi cok cok kelimeleriyle degistirilecektir. Yeni cümle "Bugün hava cok cok güzel" olacaktir. g (global) opsiyonu ile cümle icinde birden fazla bulunan regüler terimi ayni anda degistirebilirsiniz. g opsiyonunu kullanmadiginiz taktirde bulunan ilk regüler terim degistirilecektir. Diger uyan regüler terimler degistirilmez.

$var="Bugün hava cok güzel.\n"
if($var= ~/cok/)
{
$var=~ s/cok/cok cok/g;
}
print $var;


Eger string icinde bulunan bir kelimeyi silmek istiyorsaniz, s opsiyonunu asagida yer aldigi sekilde kullanabilirsiniz.

$var="Bugün hava cok güzel.\n";
if($var= ~/cok/)
{
$var=~ s/cok/ /;
}
print $var;


Daha önceden tanidigimiz i opsiyonunu kullanarak, büyük/kücük yazimi göz ardi edebilirsiniz. Asagidaki örnekte "bugün" kelimesi aranarak, cümle icinden silinmektedir.

$var=" Bugün hava cok güzel.\n";
if($var= ~/bugün/i)
{
$var=~ s/bugün/ /g;
}
print $var;


Kapsamli arama yapmak icin regüler terimlerde özel anlam tasiyan isaretler kullanabiliriz. Bu isaretleri kisaca taniyalim:

. : herhangi bir harf/isaret anlamina gelir.
[abc] : a, b ya da c.
[a-z] : a dan z ye kadar bir kücük harf.
[^a-f] : a dan f kadar harf gurubu disindaki herhangi bir kücük harf.
\w : harfle baslayan herhangi bir kelime.
\W : harfle baslamayan herhangi bir kelime.
\s : iki kelime arasindaki bosluk.
\d : 0 ila 9 arasinda herhangi bir sayi.
^ : satir baslangici.
$ : satir sonu.
(abc|de): abc ya da de iceren bir kelime (ikisinden birisi).
reg* : reg olarak aranan regüler terimin bir, berden fazla ya da 0 kere kullanilmasi.
reg+ : reg olarak aranan regüler terimin bir veya birden fazla kullanilmasi.
reg? : reg olarak aranan regüler terimin 0 ya da bir kere kullanilmasi.

Belirli bir harfi ya da rakami ariyorsaniz /./ kalibini kullanabilirsiniz. . (nokta) sadece bir harf ya da rakam yerini tutar.

if($var=~/./) # En az bir harf/rakamdan olusan kelimeleri bulur.
if($var=~/...../) # En az bir 5 harf/rakamdan olusan kelimeleri bulur.
if($var=~/[A-Z]../) # Ali, Bil, Kül gibi kelimleri bulur. Büyük bir harfi iki harf/rakam takip eder.
if($var=~/[A-Z].[0-9/) # Büyük bir harf ve bir rakam arasinda herhangi bir harf/rakam olan kelimeleri bulur # Ax1, B23, Cy9 kelimelerini bulur.


Regüler Terimler - Alternatifler:
Alternatifleri kullanarak, tarama sirasinda birden fazla regüler terim kullanabilirsiniz. Listede bulunan terimlerden biri bulunana kadar, tarama islemi sürdürülür.

if($var=~/ahmet|mehmet|veli/) { print "OK"; } # $var icinde adi gecen herhangi bir ismi arar.

Regüler Terimler - Tekrarlar:
Kivantör (quantor) olarak isimlendirilen *, ?, + isaretleri kullanarak, bir kelime icinde arka arkaya kullanilan harf veya rakam gruplarini lokalize edebilirsiniz.

* operatörü ile bir harf/rakami 0, 1 yada birden fazla lokalize edebilirsiniz.
if($var=~/[A-Z]*/) # Büyük bir harfle baslayan tüm kelimeleri bulur.
if($var=~/[a-z]*[0-9]/) # 0, 1 ya da 1 den daha fazla ufak harften sonra bir rakam ihtiva eden tüm kelimeleri bulur. a1, aaaaa3, bbbbb5.......
+ operatörü ile bir harf/rakami en az 1 yada birden fazla lokalize edebilirsiniz.
if($var=~/[A-Z]+\d/) # En az 1 ya da daha fazla büyük harften sonra bir rakam iceren kelimeleri bulur. # A3, B4......
? operatörü ile bir harf/rakami 0 yada en fazla 1 defa lokalize edebilirsiniz.
if($var=~/A?/) # $var icinde ya hic A yok ya da sadece bir tane A var.
if($var=~/[A-Z]?/) # $var icinde ya büyük harf yok ya da iki tane büyük harf yan yana degil.


Daha önce ekran cikisi yapabilmek icin print() fonksiyonunu kullandik. Program icinde kullanilan degiskenlerin sahip oldugu degerler degisik uzunlukta oldugu ve degiskenlerin degerleri program süresince degistigi icin, ekran cikislarini print() fonksiyonu ile formatlamak zor olacaktir. Printf() fonksiyonunu kullanarak ekran cikisini istediginiz sekilde formatlayabilirsiniz.

printf("%d %s %03d\n", 1224, "Merhaba", 1); # Ekran cikisi: "1224 Merhaba 1"
printf("(%-20s)\n(%20s)\n", "Merhaba arkadaslar", "Nasilsiniz?");


Printf() fonsiyonu icinde kullanabileceginiz özel isaretler:

\a Alarm.
\b Backspace.
\f Form Feed - Yazici üzerinde yeni bir sayfa.
\n Newline - Yeni satir.
\r Carriage Return - Yeni satir yapmadan satir basi.
\t Yatay Tab - Bir sonraki yatay tabülator pozisyonuna gider.
\v Dikey Tab - Bir sonraki dikey tabülator pozisyonuna gider.

Perl programlariniza HERE dokümani cercevesinde print() fonksiyonunu kullanmadan text pasajlari ekleyebilirsiniz. Böylece her satir icin print() fonksiyonunu kullanmak zorunda kalmiyacaksiniz. Kitabin CGI bölümünde de görecegimiz gibi, HERE dokümanlari kullanilarak, CGI programlarina HTML sayfa kodlari eklenir.

print << TEXT;
Merhaba Arkadaslar,
bugün sinemaya gitmeye ne dersiniz?
Bugün hava cok güzel.
TEXT
$var = << TEXT;
Merhaba Arkadaslar,
bugün sinemaya gitmeye ne dersiniz?
Bugün hava cok güzel.
TEXT
print $var;


HERE dökümanlari << operatörü ve HERE ismiyle baslar. Dikkat edilmesi gereken husus, << ISIM den sonra noktali-virgül kullanilmasidir. Istenilen pasaj eklendikten sonra, HERE ismi tekrar yazilarak, HERE döküman cercevesinin kapatilmasi gerekmektedir. HERE ismini yazdiktan sonra, noktali-virgül yazmiyoruz.
En son satirda yer alan Here isminin mutlaka satir basinda yeralmasi gerekiyor. Aksi taktirde, Perl derleyisi Here dökümaninin sonunu bulamadigi icin, hata mesaji verecektir.

 

PERL'E DERSLERİ - 5

Perl dilinde kullanilan referanslar diger dillerden tanidigimiz göstergeclere (pointer) esdegerdir. Bir referans nedir? Bir degisken ile belli bir hafiza alanini adresledigimizi daha önce ögrenmistik. Referanslari kullanarak, herhangi bir degiskenin adres alanini üzerinde operasyon yapabiliriz Böylece, referansin tipine göre, referans üzerinde yapacagimiz degisklikler, degiskenin sahip oldugu degeri etkileyecektir.
Referanslari kullanarak, yüksek derecede karmasik ve dinamik programlar yazabiliriz. Dikkat edilmedigi zaman referanslar programimizin dogru calismasini engeller. Referanslar üzerinde yapilan operasyonlarla, istemeden, kullanimda olan degiskenlerin degerlerini silebilir ve degistirebiliriz. Bu göz önünüde bulundurularak, az sayida referansin kullanilmasi, programin görevini saglikli bir sekilde yerine getirmesini sagliyacaktir.
Perl dilinde iki tip referans vardir.

1. Sembolik referanslar,
2. Gercek referanslar.

Sembolik referanslar bir baska degiskenin ismini kullanarak, bu degiskenin degeri üzerinde operasyon yapabilirler. Sembolik referanslar genel anlamda kendileri ve referense ettikleri degerler degisken olduklari icin, referense edilen degerler ulasmak icin $$ isaretlerini kullanmamiz gerekiyor. Referense etmek istedigimiz veri tipine göre $$, @$, %$ kullaniyoruz.

# Degisken üzerinde sembolik referans kullanimi
$var= "Yildiz";
$semvar="var";
print $$semvar;

# Liste üzerinde sembolik referans kullanimi @araba=("Murat 131", "Sahin","Serce");
$semaraba="araba";
print @$semaraba;

# Liste üzerinde sembolik referans kullanimi
%liste=("bir", 1, "iki",2, "üc",3);
$semliste="liste";
foreach $elem (%$semliste)
{
print $elem;
}

# Subrutin üzerinde sembolik referans kullanimi
sub print
{
print "Merhaba"
}
$semsub='print';
&$semsub;


Gercek referanslar C/C++ dillerinde kullanilan göstergeclere(pointer) esgederdir. Sembolik referanslarin aksine, gercek referanslar beraberlerinde bir referans sayaci tasirlar. Bu sayac birin altina düsmedigi sürece, referense edilen hafiza alanindaki bilgi silinmez. Bunun ne anlama geldigini bir kac örnekle aciklamak istiyorum.
Örnegin bir subrutin icinde bir degisken tanimladigimizi düsünelim. Bu degisken subrutin icinde bulundugumuz sürece gecerliligini koruyacaktir. Subrutini terk ettigimiz anda, tüm local olarak tanimladigimiz degiskenler hafizadan silinir. Böylece bu degiskenlerin degerlerini ana program icinde kullanmamiz mümkün olmaz.

sub print { my $a=5; print $a; }
# Subrutin disina ciktiktan sonra $a degiskeni silinir.


Yukarda yer alan örnekte, subrutin icine girildigi andan itibaren, hafizada $a isminde bir degisken yaratilir. Son satirda yer alan print komutuyla subrutinden cikmis oluruz ve $a degiskeni hafizdan silinir.
Eger $a degiskeninin degerini ana program icinde kullanmak istiyorsak, gercek bir referans kullanarak, $a degiskenini referense edebilir ve $a degiskeninin degerini silinmekten kurtarabiliriz. Ancak ana programda $a degiskenini kullanarak, $a nin sahip oldugu degere ulasamayiz. Subrutin cikisi $a silindigi icin, anaprogram icinde böyle bir degisken mevcut olmayacaktir. Ama subrutinden cikmadan önce $a yi referense ettigimiz icin, referans ismini kullanarak, $a nin degerine ulasabiliriz.

sub print
{
my $a=5; $referans=\$a ;
}
&print;
print $$referans;
print $a;
# Son satir hatalidir, cünkü böyle bir degisken yok.
# Subrutin disina ciktiktan sonra $a degiskeni silinir.
# Ana programda $referans degiskenini kullanarak,
# $a nin degere ulasabiliriz.


\$degisken yazarak herhangi bir degiskeni referense edebiliriz.
Referans bir degiskenin sahip oldugu hafiza alani adresini icerir. Referense edilen degisken silinmis olsa bile, hafiza alani adresine sahip oldugumuz icin referans üzerinden bu bilgiye ulasabiliriz.

$var=1224;
$ptr=\$var;
print $ptr; # SCALAR(0x987c33)
# Referans bir adres icerdigi icin, print komutu bu adresi ekrana basar.
print $$ptr; # 1224


Daha önce ögrendigimiz gibi liste icinde baska bir liste yapmamiz mümkün degil. (1,2,3,(3,5)3,4) seklinde bir liste (1,2,3,3,5,3,4) olarak degerlendirilir. Bu sekilde 2 ya da 3 boyutlu bir matrix yapmamiz mümkün olmayacaktir.
Gercek referans kullanarak, bir liste elemanini diger bir listeyi gösterecek sekilde listeye yerlestirebiliriz.
Asagidaki örnegi inceleyelim.

@liste2=(3,5);
$ref=\@liste2;
@liste=(1,2,3,$ref,3,5);
foreach $elem( @liste)
{
print "$elem\n";
}
print "Alt liste\n";
print "$liste[3][0]\n";
print "$liste[3][1]\n";
#$liste[3][0], @liste2 nin birinci elemanini ekrana basar.
liste[3] listenin 4. elemani olan @liste2 yi adresler.


Referanslari kullanarak, HASH veritipi elemanlardan olusan bir liste olusturabiliriz.

$hashliste=[
{ "Bir" => 1, "Iki" => 2, "Üc" =>3 },
{ "One" =>1, "Two" =>2, "Three"=>3 } ]; $ref=\@hashliste;
print $$ref[0]{"Bir"}; # 1
print $$ref[1]{"One"}; # 1


Yazilan uzun programlarda bütün kodun bir dosya icinde yer almasi, kisa sürede kod icinde kaybolmamiza yol acabilir. Programi okunabilir ve düzenli olmasini saglamak icin kod bölümlerini ve subrutinleri baska dosyalar icine koyabiliriz. Require direktifi ile baska dosya icinde bulunan bir kodu kendi programimiza eklememiz mümkün.

################################
# var.pl icinde yer alacak kod
$var=1224;
print $var;
1;
# ana programda require
# direktifinin dogru calisabilmesi
# icin en son satirda 1 olmasi
# gerekiyor.
################################
#Ana programa var.pl dosyasini ekliyoruz
$var=111;
require "var.pl";
print $var; # 1224


Require direktifini kullanarak, programimiza disaridan kod eklememiz mümkündür. Ama Perl eklemek istedigimiz kodu nerede bulacagini nasil biliyor?
Perl derleyicis, @INC listesi icinde bulunan tüm dizinleri, eklemek istediginiz kodu bulmak icin tarar. @INC listesinin icinde yer alan dizinler:

C:\Perl\lib\MSWin32-x86
C:\Perl\lib
C:\Perl\site\5.00502\lib
C:\Perl\site\lib\MSWin32-x86
C:\Perl\site\lib


@INC listesinde yer alan dizinler sistemden sisteme degisir. Asagida yer alan programi calistirarak, sisteminiz üzerindeki Perl dizin semasini ekrana basabilirsiniz.

foreach $elem (@INC)
{
print "$elem\n";
}


Require örneginde gördügümüz gibi, disardan eklenen kodun icinde bulunan tüm degiskenler ana programda yer aldilar. Disardan eklenen kod ana programin bir parcasi olarak görülür. Bu sebepten dolayi ana programda kullandigimiz degiskenler, disardan eklenen kodun da icinde bulunabilecegi icin, zarara ugrayabilirler. Degiskenlerin gecerliliklerini koruduklari bölgeye, kod icinde isim-alani adi verilir. Bu isim-alani icinde degiskenler bellidir. Disaridan ekledigimiz kodun icinde bulunan degiskenler de, kodun icinde diger degiskenlerle ayni isim-alanini paylastiklari icin, ortaya istenmedik durumlar cikabilir. Burada, yabanci kodun, ana program icinde yer alan degiskenlerin isim-alanini kirletmeyecek sekilde, kendi isim alani icinde programa eklenmesi geregi doguyor. Aksi taktirde yabanci kodu satir satir gözden gecirerek, kullanilan degiskenleri kontrol etmemiz gerekiyor. Gözden kacirdigimiz bir degisken, programin gerektigi gibi calismasini engelleyecektir.
Isim-alanlarini birbirinden ayiracak bir mekanizmaya ihtiyacimiz var. Önümüzdeki bölümün konusu ve ayri isim-alanlari olusturmada kullanabilecegimiz paketler olacak.
Paketler yardimiyla isim-alanlarini birbirinden ayirabiliriz. Bir paket nedir ? Dilerseniz önce bu soruyu cevaplayalim.
Bir Paket basli basina bir isim-alani olusturur. Bir paket icinde yer alan tüm degisken ve subrutinler sadece paket icinde, paket ismi olmadan kullanilabilir. Paket disina cikildi zaman, paket ismini kullanarak, paket ismiyle tanimladigimiz isim-alani icindeki degisken ve subrutinlere ulasabiliriz. Böylece paket isimlerini kullanarak, isim-alanlarini birbirinden ayirmis oluyoruz.

Modüller ve Paketler:
Bir paketi, package isim; direktifini kullanarak tanimlayabiliriz. Bu direktiften sonra normal kod yazilir.

package ornek;
$var=1223;
$isim="özcan";
1;


Simdiye kadar herhangi bir paket kullanmadan, Perl programlari yazdik. Ama görmesek de, programlarimizda hep bir paket yer aldi: main. Bütün programlar main paketi ile baslar. Package komutu kullanilarak, paketler arasinda degistirme yapilir.
Simdi require direktifini kullanarak, eklenen kodda bulunan degiskenlerin ana program isim-alanini kirletmeyecek sekilde, ayri isim-alanlari yaratabiliriz.

##########################
# require ile eklenecek kod.
# var.pl
package var;
$sayi=1224;
$main::sayi= 3000;
1;
##########################
# Ana program $
sayi=1500;
require "var.pl";
print "$sayi, \n$var::sayi\n";
##########################


Program hakkinda aciklama yapmadan önce, paket kullanirken dikkat edilmesi gereken hususlara deyinmek istiyorum.
Require direktifi ile programa eklemek istedigimiz paket, isim.pl seklinde dosyalanmalidir. Perl derleyicisi, @INC listesinde bulunan dizinleri tarayarak, paketi iceren .pl dosyasini bulmaya calisir. Genelde paketi iceren dosya, eklendigi ana programin dosyasiyla ayni dizindedir.
Ana programda, requiere "paketismi.pl"; dosyasinin ana programa eklenmesini saglayacaktir.
Yukarda yer alan program nasil calisiyor? Önce ilk bölümdeki kodu var.pl ismi altinda dosyalamaniz gerekiyor. Daha sonra alt kisimda yer alan programi calisitiralim.
Program ekran cikis:

3000
1224


Ana programda $sayi degiskenini tanimladiktan sonra, require direktifi ile var paketini ana programa ekliyoruz. Paket icinde $sayi degiskenini tanimladiktan sonra main::sayi direktifiyle ana programda bulunan $sayi degiskenine 3000 rekamini esliyoruz. Paket icinde yer alan $sayi ve ana programda yer alan $sayi degiskenleri böylece birbirlerinden ayrilmis oluyor. Daha sonra ana programda, ana programin icinde tanimlanmis $sayi ve var paketinde yer alan $var::$sayi rakamlarini ekrana basiyoruz. Paket kullanilarak tanimlanmis isim-alanlarina $paketismi::$degisken seklinde ulasabiliriz.
Yukardaki örnekte görüldügü gibi, paket icinde $main::$sayi=3000; eslemesini yaparak, paket icinden, ana programda bulunan bir degiskeni degistirebiliriz.
Paket kontrüktörü BEGIN direktifi kullanilarak tanimlanir. BEGIN blogu icinde yer alan tüm komutlar pakete görevine baslamadan calistirilir. Paket kontrüktörünü kullarak, paket icinde yer alan degiskenleri belirli bir baslangic degerine esitleyebiliriz.

#################################
package pkg;
BEGIN
{
$var="$var bos degil";
}
&print_var();
sub print_var
{
print $var;
}
#################################
Paket destruktörü END direktifi kullanilarak tanimlanir. END blogu icinde yer alan komutlar program bitiminde calistirilir.
#################################
package pkg;
END
{
$var="$Program sonu geldi.";
}
&print_var();
sub print_var
{
print $var;
}
#################################
Perl modülü bir .pm dosyasi icinde yer alan bir pakettir. Daha önce kullandigimiz paket örnegini modül olacak sekilde degistirelim:
##########################
# use ile eklenecek kod.
# var.pm
package var;
$sayi=1224;
$main::sayi= 3000;
1;
##########################
##########################
# Ana program
$sayi=1500;'
use var;
print "$sayi, \n$var::sayi\n";
##########################


Ana programda use var; yazarak, modülü programimiz icinde kullanabiliriz. Use direktifi, modül icinde bulunan degisken ve subrutinleri ana programin isim-alanina yükler. Perl icin yazilmis modülleri c:\Perl\lib dizininde bulabilirsiniz. Bu modüller .pm ekini tasir ve use direktifi ile ana programa dahil edilirler.

Nesneye Yönelik Programlama:
Nesneye yönelik programlama (OOP, object oriented programming) , C++, Eiffel ve Java diliyle ortaya cikan, yeni bir programlama tarzidir.
OOP, gercek hayatta var olan nesneler örnek alinarak yazilir. Yasadigimiz dünyada hersey bir nesnedir. Her nesnenin bir calisma tarzi ve kendine has disa yönelik davranislari vadir. Bir nesne ile interaksiyona girmek icin, nesnenin icinde ne bulundugunu bilmemize gerek yok. Belirli baglamlar (Interface) üzerinden mesajlar göndererek, nesne ile baglanti kurabiliriz. Nesne bu mesaji alir ve gerekli islemleri yapar.
Perl dilini kullanarak OOP programlar yazmamiz mümkündür. OOP tarzi programlamaya gecmeden, kullanilan bazi terimlere göz atalim.

 

Murat KUZU