taraf�ndan Guido Socher
Yazar hakk�nda:
Guido eski t�fek bir Linux fanati�i ve Perl k�r�c�s�d�r. Kendi g�rsel y�resini a�a��daki linkte bulabilirsiniz.
www.oche.de/~bearix/g/.
��erik:
|
Perl k�s�m III
�eviri : Selahattin Din�
�zet:
Perl k�s�m I size Perl hakk�nda genel bir fikir verecektir.
Perl'in k�s�m II'sinde ilk yard�mc� program yaz�ld�. K�s�m III'te ise dizilere daha yak�ndan inceleyece�iz.
Diziler
Bir dizi, kendisine bir indeks ile ula��labilen de�i�kenlerin bir listesini i�erir.
Bilindi�i gibi "normal de�i�kenler", ayn� zamanda y�ns�z(skaler) de�i�kenler olarak bilinir ve isimleri de dolar($) i�aretiyle ba�lar.
@-i�aretiyle ba�layan dizilerde de dizi bir �ok y�ns�z de�i�ken i�erir.
Bundan dolay� dizi i�inde �zel alanlar belirtti�imizde dolar i�aretini yazmay� unutmamal�y�z.
Hep beraber �u �rne�e bir g�z atal�m:
!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
# declare a new array variable:
my @myarray;
# initialize it with some data:
@myarray=("data1","data2","data3");
# access the first element (at index 0):
print "the first element of myarray is: $myarray[0]\n";
|
G�rd���n�z gibi her�eyden bahsetti�imizde @myarray yazd�k ve �zel bir elemntten bahsederken
$myarray[0] yazd�k.
Perl dizileri index 0 dan ba�larlar. Yeni indexler ise veri i�aretledi�imiz an hemn olu�turulur. Bildirme zaman�nda dizinin b�y�kl���n�n ne kadar oalca��n� bilmek zorunda de�ilsiniz.
Yukar�da g�rd���n�z gibi bir veri demetini parantezlerin arkas�na bir noktal�virg�l koyarak bir araya toplayabilirsiniz.
("data1","data2","data3")
ger�ekten anonim bir dizidir.
Bundan dolay� bu anonim diziden ikinci eleman� almak i�in
("data1","data2","data3")[1]
yazabilirsiniz:
!/usr/bin/perl -w
print "The second element is:"
print ("data1","data2","data3")[1];
print "\n"
|
Diziler �zerinde d�ng�
Perl'de foreach d�ng�s� dizinin b�t�n elemanlar� �zerinde bir d�ng� kurmay�
olanakl� k�lar.
Bu a�a��daki gibi �al���r:
#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
my @myarray =("data1","data2","data3");
my $lvar;
my $i=0;
foreach $lvar (@myarray){
print "element number $i is $lvar\n";
$i++;
}
|
Bu program �al��t�r�ld���nda �u sonucu verir:
element number 0 is data1
element number 1 is data2
element number 2 is data3
|
foreach ifadesi diziden her bir eleman� al�p d�ng� de�i�kenine sokar(yukarda �rnekteki $lvar gibi)
�unu �nemle belirtmek gerekir ki de�erler diziden kopyalanmak suretiyle d�ng�n�n i�ine sokulmuyorlar.
D�ng� de�i�keni yerine baz� i�aret�i ve d�ng� de�i�kenlerinin de�i�tirilmesi dizinin i�indeki elemanlar� de�i�tirir.
A�a��daki program dizinin i�indeki b�t�n elemanlar� b�y�k harf yapar.
Perl deki
tr/a-z/A-Z/ Unix'teki "tr" komutuna benzer. Bahsedilen ko�ullarda b�t�n harfleri b�y�k harfe �evirir.
#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
my @myarray =("data1","data2","data3");
my $lvar;
print "before:\n";
foreach $lvar (@myarray){
print "$lvar\n";
$lvar=~tr/a-z/A-Z/;
}
print "\nafter:\n";
foreach $lvar (@myarray){
print "$lvar\n";
}
|
Program� �al��t�rd���n�z zaman g�receksiniz ki sadece @myarray i�eren ikinci d�ng� de�i�kenleri b�y�k harf yapacakt�r:
before:
data1
data2
data3
after:
DATA1
DATA2
DATA3
|
Komut sat�r�
Perl II'de g�r�ld��� �zere bir &getopt fonksiyonu komut sat�r�n� okumada ve komut sat�r�yla
ger�ekle�tirilebilen herhangi bir se�ene�i kullanmada kullan�labilir.
&getopt fonksiyonu C'dekiyle ayn�d�r. Bu bir kitapl�k fonksiyonudur.
Komut sat�r�ndan de�i�ken almak i�in Perl'de kullan�lan dizi @ARGV olarak isimlendirilmi�tir.
&getopt fonksiyonu sadece bu @ARGV yi al�r ve elemanlar� de�erlendirir.
C'dekinden farkl� olarak program�n ismi dizideki ilk eleman�n i�eri�i de�il
komut sat�r�n�n ilk eleman� program ismidir.
E�er perl program�n�n ismini ��renmek istiyorsan�z $0'� okumak zorundas�n�z.
Makalemizin konusu
bu olmad��� i�in �imdilik buna de�inmeyece�iz.
Bu da
add adl� �rnek
program�m�z.
Bu program komut sat�r�ndan iki rakam al�r ve bunlar� toplar:
.... ve bu da program�m�z:
#!/usr/bin/perl -w
# check if we have 2 arguments:
die "USAGE: add number1 number2\n" unless ($ARGV[1]);
print "$ARGV[0] + $ARGV[1] is:", $ARGV[0] + $ARGV[1] ,"\n";
|
Bir Y���t
Perl'de bir diziyi y���t olarak kullanan kendinden menkul bir dizi fonksiyon
vard�r.
- push bir eleman� dizinin sonuna ekler.
- pop bir eleman� dizinin sonundan okumaya yarar.
- shift dizinin ba��ndan bir eleman� okumaya yarar.
- unshift dizinin ba�lang�c�na bir eleman eklemeye yarar.
Bir sonraki program
mevcut bir diziye iki eleman ekler:
#!/usr/bin/perl -w
my @myarray =("data1","data2","data3");
my $lvar;
print "the array:\n";
foreach $lvar (@myarray){
print "$lvar\n";
}
push(@myarray,"a");
push(@myarray,"b");
print "\nafter adding \"a\" and \"b\":\n";
while (@myarray){
print pop(@myarray),"\n";
}
|
Pop, dizinin sonundaki eleman� ��kar�r ve dizi bo�alana kadar while d�ng�s� �al���r.
Dizin Okuma
Perl'�n bir dizinin i�eri�ini okumak i�in bize sundu�u fonksiyonlar;
opendir, readdir fonksiyonlar�d�r.
readdir, bir diziye b�t�n dosya isimleriyle d�ner.
foreach d�ng�s�n� kullanarak b�t�n dosya isimlerini d�nd�re bilir ve bir isim vererek arama yapabilirsiniz.
Bu �rnek program i�inde bulunulan
dizinde verilen dosya ismini arar.
#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
die "Usage: search_in_curr_dir filename\n" unless($ARGV[0]);
opendir(DIRHANDLE,".")||die "ERROR: can not read current directory\n";
foreach (readdir(DIRHANDLE)){
print"\n";
print "found $_\n" if (/$ARGV[0]/io);
}
closedir DIRHANDLE;
|
�imdi programa bir bakal�m. �lk �nce kullan�c�n�n komut sat�r� arguman�n� sa�lay�p sa�lamad���n�
kontrol ettik. E�er sa�lanmam��sa kullan�m bilgisini ekrana bast�rd�k ve ��kt�k.
Sonra i�inde bulundu�umuz dizini a�t�k ("."). opendir fonksiyonu,
dosyalar i�in ge�erli olan
the open functionsile ayn�d�r.
�lk arg�man readdir ve closedir fonksiyonlar�n� ge�mek i�in gerekli olan
dosya tan�mlay�c�s�d�r.
�kinci arg�man dizine a��lan patikad�r.
Sonraki foreach d�ng�s�ne gelir.
�lk ilgi�ekici durum d�ng� de�i�keninin atlanmas�d�r.
Perl bu durumda sizin i�in sihirli bir form�l geli�tirir ve $_ ad�nda bir de�i�ken olu�turur.
Bu de�i�ken de d�ng� de�i�keni olarak kullan�l�r.
readdir(DIRHANDLE) fonksiyonu bir diziye d�ner ve biz de her elemana bakmak i�in foreach d�ng�s� kullan�l�r.
/$ARGV[0]/io ise $ARGV[0] i�indeki s�radan ifadeyi $_ de�i�kenine ile e�le�tirilir(kar��la�t�r�l�r).
Burdaki io ise aramay� b�y�k k���k harf e�le�tirmesiz yapmas�n� ve s�radan ifadeyi sadece bir kere derlemesini ifade eder.
Bir sonraki ise program� daha h�zl� hale getiren bir iyile�tirmedir.
S�radan ifadenin i�inde bir de�i�keniniz oldu�u zaman bunu kullanabilirsiniz ve emin olabilirsiniz ki de�i�ken �al��t�rma an�nda de�i�mez.
�imdi bir deneyelim. Varsayal�m ki i�inde bulundu�umuz dizinde article.html, array1.txt ve array2.txt ad�nda dosyalar olsun. Sonra "HTML" ile aratt���m�zda �u sonu� verilecektir.
>search_in_curr_dir HTML
.
..
article.html
found article.html
array1.txt
array2.txt
G�rd���n�z gibi readdir fonksiyonu 2 tane fazladan dosya buldu. "." ve
"..". Bunlar i�inde bulunulan ve bir �nceki dizinlerin isimleri.
Bir dosya bulucusu
Bu makaleyi biraz karma��k ve daha kullan��l� bir �rnekle bitirmek istiyorum.
Bu bir dosya bulma program� olacak. Program�m�z�n ad�n� pff((perl file
finder) perl dosya bulucusu) koyal�m.
Bu temel olarak yukardaki program gibi �al��acak fakat farkl� olarak al dizinlerde de arama yapabilecek.
Peki b�yle bir program� nas�l yapaca��z? Yukarda i�inde bulunulan dizinde arama yapan baz� kodalar�m�z vard�.
��inde bulundu�umuz dizinden ba�lamam�z gerekir fakat (. ve .. d���nda) e�er i�inde bulundu�umuz dizinin i�inde ba�ka dizinler de varsa bunlar�n i�inde de arama yapmak gerekir.
Bu tipik bir yinelemeli algoritmad�r.
sub search_file_in_dir(){
my $dir=shift;
...read the directory $dir ....
...if a file is again a directory
then call &search_file_in_dir(that file)....
}
if (-d "$file" && ! -l "$dir/$_"){....} yap�s�n� kullanarak bir dosyan�n dizin mi yoksa bir symlink mi oldu�unu anlayabilirsiniz.
�imdi program� yazabilmek i�in gereken b�t�n codlar�m�z� alal�m.
the actual code (pff.gz).
#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
# written by: guido socher, copyright: GPL
#
&help unless($ARGV[0]);
&help if ($ARGV[0] eq "-h");
# start in current directory:
search_file_in_dir(".");
#-----------------------
sub help{
print "pff -- perl regexp file finder
USAGE: pff [-h] regexp
pff searches the current directory and all sub-directories
for files that match a given regular expression.
The search is always case insensitive.
EXAMPLE:
search a file that contains the string foo:
pff foo
search a file that ends in .html:
pff \'\\.html\'
search a file that starts with the letter \"a\":
pff \'^a\'
search a file with the name article<something>html:
pff \'article.*html\'
note the .* instead of just *
\n";
exit(0);
}
#-----------------------
sub search_file_in_dir(){
my $dir=shift;
my @flist;
if (opendir(DIRH,"$dir")){
@flist=readdir(DIRH);
closedir DIRH;
foreach (@flist){
# ignore . and .. :
next if ($_ eq "." || $_ eq "..");
if (/$ARGV[0]/io){
print "$dir/$_\n";
}
search_file_in_dir("$dir/$_") if (-d "$dir/$_" && ! -l "$dir/$_");
}
}else{
print "ERROR: can not read directory $dir\n";
}
}
#-----------------------
|
�imdi birazc�k program� inceleyelim. �lk �nce kullan�c�n�n komut sat�r�na ge�erli komutu girip girmedi�ini test ettik. E�er de�ilse bir hata mesaj� ��kart�p k���k bir yard�m yaz�s� ��karaca��z. Ayr�ca -h se�ene�i verilirse ayr� bir yard�m metni g�sterece�iz.
Aksi durumda i�inde bulundu�umuz dizinden itibaren aramaya ba�lar�z.
Yukarda tan�mlanan yinelemeli(recursive) algoritmay� kullan�r�z.
Dizini oku, dosyalar� ara, dosyan�n bir dizin olup olmad���n� test et, e�er olumlu ise(dizin ise) search_file_in_dir() fonkisoyunu tekrar �a��r.
�fadenin i�inde, dizinleri kontrol etti�imiz yerde ayn� zamanda dizinin ba�ka bir dizine link olmad���n� da kontrol etmi� oluruz.
Bunu kontrol etmemiz gerekir ��nk� belki birisi ".." dizinine sym-l�nk olu�turmu�tur.
B�yle bir kontrol yap�lmad��� takdirde program sonsuz d�ng�ye girecektir.
next if ($_ eq "." || $_ eq ".."); ise hen�z �zerinde konu�mad���m�z bir ifadedir.
"eq" operator ise Perl'deki katar kar��la�t�rma operat�r�d�r.
Burda ise $_ de�i�keninin i�eri�ini ".." veya "." e�it olup olmad���n� anlamak i�in test ettik.
E�er bu e�itse "next" ifadesi �al��t�r�ld�.
Bir foreach d�ng�s� i�indeki "next" ifadesi d�ng�n�n en ba��na d�n�l�p dizinin ikinci eleman� ile d�ng�ye devam edilmesi anlam�na gelir.
Bu C'deki "continue" durumuna benzer.
Kaynaklar
A�a��da Perl hakk�nda yaz�lm�� baz� ilgin� yaz�lar�n bir listesini veriyoruz.
Bu yaz� i�in g�r�� bildiriminde bulunabilirsiniz
Her yaz� kendi g�r�� bildirim sayfas�na sahiptir. Bu sayfaya yorumlar�n�z� yazabilir ve di�er okuyucular�n yorumlar�na bakabilirsiniz.
2001-03-09, generated by lfparser version 2.9