Home Map Index Search News Archives Links About LF
[Top bar]
[Bottom bar]
Bu makalenin farklı dillerde bulunduğu adresler: English  Castellano  Deutsch  Francais  Nederlands  Turkce  

convert to palmConvert to GutenPalm
or to PalmDoc

[Photo of the Author]
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ç

[Illustration]

Ö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:
> add 42 2
42 + 2 is:44
.... 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. 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.
 talkback page 

Görselyöre sayfalarının bakımı, LinuxFocus Editörleri tarafından yapılmaktadır
© Guido Socher, FDL
LinuxFocus.org

Burayı klikleyerek hataları rapor edebilir ya da yorumlarınızı LinuxFocus'a gönderebilirsiniz
Çeviri bilgisi:
en -> -- Guido Socher
en -> tr Selahattin Dinç

2001-03-09, generated by lfparser version 2.9