Bölüm 7: Dosyada Metin Arama
Bu bölümde bir dosyanın içerisinde belli bir metni nasıl aratabileceğimizi anlatacağım. Eğer bütün sitede arama yaptırmak istiyorsanız bunu kendiniz yapmanızı tavsiye etmem. Bunun için Glimpse ve SWISH gibi hazır site indexleme araçlarını kullanabilirsiniz. (SWISH'i tavsiye ederim)
Dosyada arama yaptırmanın değişik yolları vardır. Eğer bir tek dosyada arama yaptıracaksanız, bir döngü ile dosyadaki bütün kayıtları teker teker okutup aradığınız verinin o kayıtta geçip geçmediğini kontrol edebilir, ya da Perl'ün grep() fonksiyonunu kullanarak dosyanın tamamını bir seferde tarayabilirsiniz. Birinci yolu geçen bölümde öğrendiğimiz bilgilerle yapabilirsiniz. Bu bölümde ikinci yol olan grep() fonksiyonunu kullanarak bunu nasıl yapabileceğinizi anlatacağım.
grep() fonksiyonunun kullanımı aşağıdaki gibidir.
@sonuclar = grep(/$arananmetin/,@liste);
Sanırım bir örnek verirsek daha iyi anlaşılır.
#!/usr/bin/perl
@liste = ("sinan","koray","baris","orhan");
$arananmetin = "an";
@sonuclar = grep(/$arananmetin/,@liste);
foreach $i (@sonuclar) { print "$i\n"; }
Bu programın çıktısı aşağıdaki gibi olur.
sinan
orhan
Şimdi biraz daha gelişmiş bir örnek verelim. Aşağıdaki gibi, öğrencilerin okul numarası, isim ve yaş bilgilerinin kaydedildiği "ogrenci.txt" isimli bir veritabanı dosyamız olsun.
1|768|Hasan Şahin|15
2|515|Mustafa Öztürk|16
3|663|İlhan Yıldırım|16
4|697|Fikret Yılmaz|15
5|716|Haluk Çiçek|15
Şimdi de bu veritabanında arama yaptırmak için bir script yazalım.
#!/usr/bin/perl
$veridosyasi = "ogrenci.txt";
read(STDIN, $tampon, $ENV{'CONTENT_LENGTH'});
@ciftler = split(/&/, $tampon);
foreach $cift (@ciftler) {
($alanadi, $deger) = split(/=/, $cift);
$deger =~ tr/+/ /;
$deger =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$deger =~ s/~!/ ~!/g;
$FORM{$alanadi} = $deger;
}
$arananmetin = $FORM{'isim'};
open(DOSYA,$veridosyasi);
@bilgiler = <DOSYA>;
close(DOSYA);
print "Content-type:text/html\n\n";
print "<html><head><title>Arama Sonuçları</title></head>\n";
print "<body><h3>Arama Sonuçları</h3>\n";
$bulunansayisi = 0;
@sonuclar = grep(/$arananmetin/,@bilgiler);
if ($#sonuclar >= 0) {
foreach $i (@sonuclar) {
chomp($i);
($kayitno,$okulno,$adsoyad,$yas) = split(/\|/,$i);
print "<b>$adsoyad</b> Okul No: $okulno Yaş: $yas<br>\n";
$bulunansayisi++;
}
print "<br><b>$bulunansayisi</b> kayıt bulundu.<p>\n";
}
else {
print "Kayıt Bulunamadı.<p>\n";
}
print "</body></html>\n";
Bu programı "ogrenci1.cgi" adıyla kaydedin. Şimdi sıra bu scripti çağıracak formu hazırlamaya geldi.
<form action="http://hammer.prohosting.com/~sinan/cgi-bin/ornek/ogrenci1.cgi">
Aradığınız kişinin ismini girin <input type="Text" name="isim"> </form>
Not: $#sonuclar @sonuclar dizisinin eleman sayısının bir eksiğini verir.
Formumuzdaki kutucuğa "Hasan" (tırnak koymadan) yazarsanız script size "Hasan Şahin" isimli öğrenciye ait bilgileri verir. Fakat, script kayıtları alan ayırımı yapmadan taradığı için isim yerine örneğin "15" (tırnaksız) yazarsak bize 15 yaşındaki ve okul numarasında 15 geçen öğrencilere ait bilgileri verir. Bunu hatayı gidermek için scriptimizi aşağıdaki şekilde değiştirmemiz gerekir.
#!/usr/bin/perl
$veridosyasi = "ogrenci.txt";
read(STDIN, $tampon, $ENV{'CONTENT_LENGTH'});
@ciftler = split(/&/, $tampon);
foreach $cift (@ciftler) {
($alanadi, $deger) = split(/=/, $cift);
$deger =~ tr/+/ /;
$deger =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$deger =~ s/~!/ ~!/g;
$FORM{$alanadi} = $deger;
}
$arananmetin = $FORM{'isim'};
open(DOSYA,$veridosyasi);
@bilgiler = <DOSYA>;
close(DOSYA);
print "Content-type:text/html\n\n";
print "<html><head><title>Arama Sonuçları</title></head>\n";
print "<body><h3>Arama Sonuçları</h3>\n";
$bulunansayisi = 0;
@sonuclar = grep(/$arananmetin/,@bilgiler);
if ($#sonuclar >= 0) {
foreach $i (@sonuclar) {
chomp($i);
($kayitno,$okulno,$adsoyad,$yas) = split(/\|/,$i);
if ($adsoyad =~ $arananmetin) {
print "<b>$adsoyad</b> Okul No: $okulno Yaş: $yas<br>\n";
$bulunansayisi++;
}
}
}
if ($bulunansayisi == 0) {
print "Kayıt Bulunamadı.<p>\n";
}
else {
print "<br><b>$bulunansayisi</b> kayıt bulundu.<p>\n";
}
print "</body></html>\n";
Not: if ($adsoyad =~ $arananmetin) satırı $arananmetin değişkenine atanan metnin, $adsoyad değişkenine atanan metnin içerisinde geçip geçmediğini bulmak için kullanılmıştır.
Bu örnekte $bulunansayisi isimli değişkenin değeri sadece aranan metin "isim" alanında bulunduğu zaman arttırılır. Eğer aranan metin "isim" alanında değil de örneğin "yaş" alanında bulunursa kayıt ekrana yazdırılmaz ve $bulunansayisi değişkeninin değeri arttırılmaz. Scriptin sonunda $bulunansayisi değişkeninin değeri kontrol edilir ve eğer 0'sa "Kayıt bulunamadı" mesajı yazdırılır.