; #kalan satırlar @kullanicilar dizisine okunur.
9: close (WOUT); #WOUT dosyasıyla işimiz bitti.Sistem kaynaklarını tüketmemek için kapattık.
10: foreach $kullanicilar (@kullanicilar) {#@kullanicilar'ın her bir elemanı, kullanıcı bilgisinin 1 satırını içerir.
11: $kullanicilar =~ s/ .*//; # programımız, bu satırın ilk kelimesine(kullanıcı adı) ihtiyaç duyar# .Bu yüzden 10,11 ve
12: } #12 satırlarda döngü tamamlanınca newline hariç her şey temizlenir dizide sadece kullanıcı listesi bulunur.
13: print ("Saat: $saat ");
14: print ("Halen bagli olan kullanicilar:\n");
15: $oncekikullanici = "";
16: foreach $kullanici (sort @kullanicilar) { #kullanıcılar alfabetik sıralanıyor
17: if ($kullanici ne $oncekikullanici) ##Birden fazla aynı kullanici bağlantısı varsa, $oncekikullanici son basılan
#kullanici adını tutar. Ve $kullanici içindeki değer, $oncekikullanici ile aynı ise basılmaz
18: print ("\t$kullanici"); # ve uygun ise basılır
19: $oncekikullanici = $kullanici;
20: }
21: }
çalışması;
ertan> ./program.pl
Saat: 11:24
Halen bagli olan kullanicilar:
ertan
ftpadmin
poyraz
DOSYADAN DOSYAYA YÖNLENDİRME
Unix' te standart error ve standart çıktıyı aynı dosyaya yönlendirir. sh komutu olarak şöyle yazılır.
$ program >dosya1 2>&1
Aşağıdaki program standart çıktı ve standart error dosyalarının yönlendirilişiyle ilgili bir örnektir. Örnek :
çalışması; programın ekrana çıktısı yoktur.Çıktı Yazdir isimli dosyayadır. Yazdir isimli çıktı dosyasının içeriği şöyledir.
Satir 2
Satir 1
Sıralı yazmadığını gördük çünkü işletim sisteminin özelliğinden dolayı değerler buffer' dadır ve buradan önce STDERR ' e yazar. Bu problemi çözmek istersek dosya için buffer' ı kullanmama işlemi yapılır. Önce select ile dosya seçilir. Sonra $| sistem değişkenine 1 atanır. Eğer $| değişkenine 0 olmayan değer atanırsa buffer kullanılmaz. Tıpkı $~ ve $^ gibi $| da son kullanılan dosyaya etkilidir ki o dosya select ile son seçilendir. Eğer select kullanılmamışsa STDOUT'dur.
Şimdi $| kullanarak önceki örnekten farklı olarak sırayla yazan programı görelim. Örnek :
#!/usr/local/bin/perl
open (STDOUT, ">Yazdir") || die ("STDOUT dosya acma hatasi");
open (STDERR, ">&STDOUT") || die ("STDERR dosya acma hatasi");
select (STDOUT);
$| = 1; #buffer'ı kapat.Seçilen dosya yazdırma kanalını aç,seçilen dosya bir önceki satırda belirlendi:STDOUT.
# Not: Aslında STDOUT default dosya olduğundan onu select ile seçmeye gerek yoktu sadece $| = 1; yeterliydi.
print STDOUT ("Satir 1\n");
print STDERR ("Satir 2\n");
close (STDOUT);
close (STDERR);
Yazdir dosyası içeriği aşağıdaki gibidir.
Satir 1
Satir 2
OKUMA VE YAZMA ERİŞİMİ TANIMLAMA
Okuma ve yazma erişimi ile dosyayı açmak için dosya adından önce +> kodlanır.
open (OKUYAZ, "+>dosya.dat");
bu erişimle dosyanın bir kısmının üzerine yazma hakkı almış olursunuz. Bu tip kullanımlarda en verimli çalışma seek ve tell fonksiyonlari ile birlikte gerçekleştirilir. Bunlar dosyada karakter(ler) atlama işlevi sağlar. İlerde inceleyeceğiz.
ayrıca +< eki' de okuma ve yazma amaçlı tanımda kullanılabilirler.
open (OKUYAZ, "+
< eki okuma amaçlı tanımdır bu demektir ki aşağıdaki iki örnek aynıdır.
open (OKU, "
open (OKU, "dosya.dat");
close Fonksiyonu : dosya kapatır. Eğer | ile komut şeklinde kullanıldıysa (open (DOSYA, "cat dosya*|"); ) gibi O takdirde komut bitene kadar program bekler. print, printf, write Fonksiyonu : Bunları görmüştük.
select Fonksiyonu : Bir dosyayı default yapmak için kullanılır. Bunu da görmüştük.
eof Fonksiyonu : Dosya sonunu kontrol eder. Okunacak kayıt kalmamışsa 0 olmayan değer döndürür. Eğer okunacak kayıt varsa 0 döndürür. <> işaretlerinden etkilenir. eof and eof() farklıdır. eof nin <> işaretlerden nasıl etkilendiği görülür. Aşağıdaki örnekte bu durumu gözleyebiliriz. Örnek programda komut satırından isimleri verilen dosyalar(1 veya daha çok)'ın içeriği basılır. dosya1 içeriği şöyle olsun;
Bu ilk dosyanın ilk satırı
Bu ilk dosyanın ikinci satırı
Dosya2 içeriği ise ;
Bu ikinci dosyanın ilk satırı
Bu ikinci dosyanın ikinci satırı
Örnek : eof ve <> birlikte kullanımı;
#!/usr/local/bin/perl
while ($kayit = <>) {#<>operatörü der ki; adları komut satırında verilen dosyalardan ,okunmakta olanın sıradaki satırını oku
print ($kayit); # ve yazdır.
if (eof) { #dosya sonu geldiyse aşağıdaki mesaji bas
print ("-- Kullanımdaki dosyanın Sonu --\n");
}
}
çalışması; ./program.pl dosya1 dosya2
Bu ilk dosyanın ilk satırı
Bu ilk dosyanın ikinci satırı
-- Kullanımdaki dosyanın Sonu --
Bu ikinci dosyanın ilk satırı
Bu ikinci dosyanın ikinci satırı
-- Kullanımdaki dosyanın Sonu --
dosya sonu kontrolünde eof ve eof() kullanılır ama ikisi birlikte kullanılmaz.
Şimdi de parantezli eof kullanımına bakalım.Örnek :
#!/usr/local/bin/perl
while ($kayit = <>) {
print ($kayit);
if (eof()) {
print ("-- Kullanımdaki dosyanın Sonu --\n");
}
}
çalışması ;
./program.pl dosya1 dosya2
Bu ilk dosyanın ilk satırı
Bu ilk dosyanın ikinci satırı
Bu ikinci dosyanın ilk satırı
Bu ikinci dosyanın ikinci satırı
-- Kullanımdaki dosyanın Sonu --
Çıktıyı incelediğinizde dosya sonu mesajının her dosyanın sonunda değil tüm dosyaların okunması Sonunda bir defa yazdığını görüyorsunuz. eof() kullanımında ancak tüm dosyalar bitince true döner. Birinci dosya sonunda kontrolde false 'e döner. Çünkü sırada okunacak ikinci dosya vardır. Yalnız şuna dikkat etmemiz gerekir eof ile eof() arasında sadece <> operatörüyle kullanımda fark vardır. Yalnız başlarına kullanımda eof ile eof() arasında fark yoktur.
DOSYA İSİMLERİNİN DOLAYLI KULLANIMI
$dosya = "DOSYAM";
open ($dosya, ">dosya.dat"); gibi...
Örnek :
#!/usr/local/bin/perl
&dosya_ac("OKU", "", "dosya1");
&dosya_ac ("YAZ", ">", "dosya2");
while ($satir = &dosyadan_oku("OKU")) {
&dosyaya_yaz("YAZ", $satir);
}
sub dosya_ac {
local ($dosya_degiskeni, $dosya_modu, $dosya_adi) = @_;
open ($dosya_degiskeni, $dosya_modu . $dosya_adi) ||
die ("$dosya_adi dosyası açılamadı... ");
}
sub dosyadan_oku {
local ($dosya_degiskeni) = @_;
<$dosya_degiskeni>;
}
sub dosyaya_yaz {
local ($dosya_degiskeni, $satir) = @_;
print $dosya_degiskeni($satir);
}
çalışması, program ekrana çıktı vermez. dosya1 adlı dosyayı dosya2 ye kopyalar. more dosya1 veya cat dosya1 gibi komutlarla baktığımızda her iki dosyanın da içerik olarak aynı olduğunu görürüz.
$ cat dosya1
Bu ilk dosyanın ilk satırı
Bu ilk dosyanın ikinci satırı
$ cat dosya2
Bu ilk dosyanın ilk satırı
Bu ilk dosyanın ikinci satırı
DATALARI ATLAMA VE YENİDEN OKUMA
== seek == == tell ==
Şimdiye kadar hep ilk sıradan başlatarak okuma örnekleri gördük. Perl bize iki hazır fonksiyon sunar.Bunlar seek ve tell fonksiyonlarıdır. Bu fonksiyonlar dosyada ileri, geri hareketi veya tekrar okuma gibi işlevlere sahiplerdir.
seek fonksiyonu : bu fonksiyon dosya içinde ileri ve geri hareketi sağlar. Formatı ;
seek (dosyadeğişkeni, atlanacak karakter sayısı, konum_sabiti);
eğer konum sabiti;
0 ise; dosya başı
1 ise; bulunulan konum değeri
2 ise; dosya sonu anlamı taşırlar.
Örneğin; DOSYAM adlı dosyanın başına atlamak istiyorsak
seek (DOSYAM, 0, 0);
kodlanır. Aşağıdaki ifade bulunulan karakter pozisyonundan 80 byte (karakter) ileri atlar.
seek (DOSYAM, 80, 1);
aşağıdaki ifade ise 80 karakter geri gider.
seek (DOSYAM, - 80, 1);
dosya sonuna atlamak için ise;
seek (DOSYAM, 0, 2);
seek başarılı olursa true(0 olamayan değer) aksi takdirde false(0) döndürür. seek ,tell fonksiyonu ile çok sık kullanılır.
tell Fonksiyonu : Mesafe döndürür.
Bu mesafe dosya başı ile bulunulan pozisyon(bir sonra okunacak satır bölgesi) arası mesafedir.Birimi byte' dır. Formatı;
tell (dosya_değişkeni);
o an kullanılacak olan dosyanın adını saklayan değişken örneğin DOSYAM ' ın kullanım anındaki pozisyonunu elde eden kodlama şu şekilde yazılır.
$pozisyon = tell (DOSYAM);
seek ve tell kullanımı örneği içeren bir program yazalım. Çalışacağımız dosyanın adı dosya1 ve içindeki kayıtlar şöyle olsun;
Ertan TURKMEN ANKARA TURKIYE
JOE ROSE NEWYORK USA
ŞAZİYE MORAL ISTANBUL TURKIYE
DANIYAR ANDICAN TASKENT OZBEKISTAN
Örnek:
#!/usr/local/bin/perl
open (GECICI_DOSYA, "dosya1");
print "Dosya yazdırılıyor ..!\n\n";
print "DOSYANIN ILK KAYDI--";
while (1) {
$satir = ;
last if ($satir eq "");
print ($satir);
if (eof()) {
print "DOSYA SONU\n";
last;
}
$pozisyon = tell(GECICI_DOSYA);
$pozisyon++;
print "--Yeni SATIR--Dosyada $pozisyon.karakterdeyiz\n";
print "5 karakter sonrası: ";
seek (GECICI_DOSYA, 5, 1);
}
çalışması: program.pl
Dosya yazdırılıyor ..!
DOSYANIN ILK KAYDI--Ertan TURKMEN ANKARA TURKIYE
--Yeni SATIR--Dosyada 30.karakterdeyiz
5 karakter sonrası: OSE NEWYORK USA
--Yeni SATIR--Dosyada 51.karakterdeyiz
5 karakter sonrası: E MORAL ISTANBUL TURKIYE
--Yeni SATIR--Dosyada 81.karakterdeyiz
5 karakter sonrası: AR ANDICAN TASKENT OZBEKISTAN
DOSYA SONU
dosya değişkeni pipe (|)' a refere ediyorsa tell ve seek kullanılamaz. Örneğin;
open (DOSYAM, "cat dosya*|"); olursa aşağıdaki satır anlamsızdır
$satir = tell (DOSYAM)
SİSTEM OKUMA YAZMA FONKSİYONLARI
Perl' de şeklindeki ifade dosyadan en temel okuma şeklidir. Bunun dışında dosyadan okuma için iki fonksiyon daha vardır. Bunlar;
-
read : unix' de ki fread fonksiyonu gibidir
-
sysread : read fonksiyonuna eş değerdedir
Perl yazmak için de fonksiyonlar sunar. Örneğin unix' de ki write' a benzeyen syswrite fonksiyonu gibi.read Fonksiyonu: okuma yapar ve isteğe bağlı karakter sayısını skalar değişkene atar.
read (dosyadegiskeni, sonucdegiskeni, uzunluk, atlamadegeri);
okunacak skalar veya okunacak dosya' ı temsil array değişken karakter sayısı eder.(okunan buraya depolanır) Örn:
read (DOSYAM, $skalar, 80);
bu çağrı ile DOSYAM' dan 80 karakter(byte) okunur ve $skalar değişkenine depolanır. Eğer DOSYAM dosyasının sonuna gelinirse 0' a döndürür, normalde okunan karakter(byte)leri döndürür. Eğer hata oluşursa read, null string döndürür. read kullanılarak skalar değişkene bir argüman eklenebilir. Bu argüman değişken içinde atlanacak byte sayısını verir. Örn:
read (DOSYAM, $skalar, 40, 80);
komutu ile read, DOSYAM' dan bir başka 40 byte okur ve bunu $skalar 'a kopyalarken daha önce depolanmış 80 byte'ı atlar.
sysread Fonksiyonu : Mümkün olduğunca hızlı data okumak için read yerine sysread kullanabilirsiniz.
Formatı; sysread (dosyadegiskeni, sonucdegiskeni, uzunluk, atlamadegeri( isteğe bağlı ));
Örn:
sysread (DOSYAM, $skalar, 80);
sysread (DOSYAM, $skalar, 40, 80); read ile kullanımı aynıdır.
sysread UNIX' in read komutu ile aynıdır.
syswrite Fonksiyonu : Bu fonksiyonda olabildiğince hızlı yazmak için kullanılır. UNIX' deki write komutuyla aynıdır. Formatı:
(dosyadegiskeni, sonucdegiskeni, uzunluk, atlamadegeri);
syswrite (dosyadegiskeni, data, uzunluk, atlamadegeri);
yazılacak datanın byte atlama dosyayı temsil nerede olarak değeri eder. olduğu uzunluk ( isteğe bağlı )
Örnek:
syswrite (DOSYAM, $skalar, 80);
$skalar' ın 80 byte' ını DOSYAM' a yazar.
syswrite (DOSYAM, $skalar, 40, 80);
$skalar' da ki ilk 80 byte' ı atladıktan sonra sonraki 40 byte' ı, DOSYAM' a yazar.
Geniş bilgi için UNIX' in read ve write komutlarına bakınız.
getc Fonksiyonu Kullanarak Karakter Okuma : dosyadan bir karakter okur. Formatı;
$karakter = getc (dosya);
döndürülen okunacak dosya karakter Örn:
$tek = getc(dosya);
dosya' dan tek karakter okur, $tek ' e kopyalar.getc, hotkeys uygulamalarında çok yararlıdır. Örnek :
#!/usr/local/bin/perl
&hot_keys_baslat;
while (1) {
$tek_al = getc(STDIN);
last if ($tek_al eq "\\"); # \ karakteri giriş sonu olacak
$tek_al =~ tr/a-zA-Z0-9/b-zaB-ZA1-90/; # ne yazılırsa bir sonrakini elde eder
print ($tek_al);
}
&hot_keys_son;
print ("\n");
sub hot_keys_baslat {
system ("stty cbreak");
system ("stty -echo");
}
sub hot_keys_son {
system ("stty -cbreak");
system ("stty echo");
}
Çalısması:
program çalıştığında siz ne yazarsanız bir sonrakini yazar. Yani a yazarsanız b , 1 yazarsanız 2 gibi...
-- Programdan çıkmak için \ tuşuna basınız .--
a1d yazarsak, ekranda b2e görünür. hot_keys_baslat alt programı, hot key girişi için çalışma çevresini düzenler. system fonksiyonu, argüman alır ve icra eder. stty -cbreak, bir anda bir karakter almasını sisteme söyler. stty echo ise yazılan karakterin ekranda görülmemesini söyler. hot_keys_son altprogramı ise normal çalışma moduna döndürür.
binmode Fonksiyonu :
bu fonksiyon kullanılarak binary dosya okunur. Format;
binmode (dosya değişkeni);
binmode (DOSYAM);
normalde DOS ve benzeri çevrede çalışmadıkça buna ihtiyacınız yoktur.
FORMATLI YAZDIRMA
Tanımlama: Aşağıdaki tanım basit bir örnektir.
format FORMATIM =
===================================
B a s k ı F o r m a t ı d ı r
===================================
syntax:
format FORMAT_ADI =
----
---- çıktı satırları
----
----
.
BASKI FORMATINI GÖSTERME
Bu işlem için iki şeye ihtiyaç vardır. Kullanmak istediğiniz formatı, $~ sistem değişkenine(sistem değişkenlerini göreceğiz), set edin. write fonksiyonunu çağırın. Bununla ilgili bir örnek program görelim.Ör. program:
#! /usr/bin/perl
$~="FORMATIM";
write;
format FORMATIM =
=====================
g ö r mek i s t e d i ğ i n i z t e x t
=====================
.
çalıştır ¿
=====================
g ö r mek i s t e d i ğ i n i z t e x t
=====================
İzah: format adı ( FORMATIM ) sistem değişkenine ($~) atandığında perl şunu anlar. write fonksiyonu kullanıldığında atanan format basılacaktır. Son kısımda ise formatın tanımlanması vardır.
eğer $~ sistem değişkenine atanma olmasaydı, yazdırma işlemi standart çıktıya (STDOUT) olacak şeklinde algılanacaktı.
BASKI FORMATINDA DEĞERLERİ GÖSTERME
Tabi ki bu işlemin amacı değişken ve dizilerdeki değerlerin uygun biçimde yazdırılmasıdır. Ör. program:(Sesli harfleri bulur sayar ve basar)
1:#!/usr/local/bin/perl
2:
3: while ($kayit = ) {
4: $kayit =~ s/[^aeiou]//g;
5: @sesliler = split(//, $kayit);
6: foreach $sesli (@sesliler) {
7: $seslisayisi{$sesli } += 1;
8: }
9: }
10: $~ = "SESLIFORMAT";
11: write;
12:
13: format SESLIFORMAT =
14: ==========================================================
15: text içindeki sesli adedi:
16: a: @<<<<< e: @<<<<<
17: $seslisayisi {"a"}, $seslisayisi {"e"}
18: i: @<<<<< o: @<<<<<
19: $seslisayisi {"i"}, $seslisayisi {"o"}
20: u: @<<<<<
21: $seslisayisi {"u"}
22: ==========================================================
23: .
çalıştırılır¿
Bu bir sesli harf bulma testidir.
Kartal Cimbomu yendi.
^D
==========================================================
text içindeki sesli adedi:
a: 4 e: 3
i: 6 o: 1
u: 3
==========================================================
çalışması: satır girilir.
4. satırda; a,e,i,o,u dışındakiler elenir
5. satırda; kalanlar(sesli) @sesliler dizisine aktarılır.
6. satırda; sesliler sayılır (@sesliler dizisi test edilerek) ve %seslisayisi bileşik dizisine eklenir.
10. satırda; basım formatı SESLIFORMAT olarak Set edilir.
Değer alanları formatları için tanımlanan değerler hakkında 3 şeyi not etmeliyiz.
-
alanların içerikleri basılır.
-
alan boşluklarını hizalamaya gerek yoktur.
-
alanlar bir üst satırda tanımlı formata uygun tanımlanırlar.
DEĞER ALANI FORMATI SEÇİMİ
Geçerli değer alanı formatları tablosu
Alan
|
Değer Alan Formatı
|
@<<<
|
sola dayalı baskı
|
@>>>
|
sağa dayalı baskı
|
@|||
|
merkeze dayalı baskı
|
@##.##
|
sabit noktalı sayısal baskı
|
@*
|
çok satırlı text
|
@* haricinde tüm tanımlarda alan ölçüsü tanımlı karakter sayısı kadardır. Bu sayıya @ karakteri dahildir.
Örneğin;
-
@>>>> tanımı 5 karakter uzunluğu belirtir. Benzer şekilde
-
@##.## uzunluğu 6 dır(. da dahil)
ÇOK SATIRLI ALAN FORMATI KULLANIMI
Ör prog.
#!/usr/local/bin/perl
@kayit = ;
$karakterler = join("",@kayit);
$~ = "SATIRLAR";
write;
format SATIRLAR =
****** Girdiğiniz dosyanin icindekiler: ******
@*
$karakterler
*****************************************
.
çalıştır:
program.pl ¿
ilk satir
ikinci satir
ucuncu satir
****** Girdiğiniz dosyanin icindekiler: ******
ilk satir
ikinci satir
ucuncu satir
*****************************************
2. satır file'ın tamamını @input dizisine atar. Her bir satır dizinin bir elemanı olarak yerleşir.
3. satır girilen satırları tek karakter stringi olarak $stringe birleştirerek yerleştirir. Bu karakter stringi newline karakterlerini de içermektedir.
6. satır formatı çağırarak bastırır . @*tanımı çok satırlı text olarak formatlar.
DİĞER ÇIKTI DOSYALARINA YAZMA
Şu ana kadar write fonksiyonu ile standart çıktı dosyasına yazılma örnekleri gördük. Diğer dosyalara da yazdırabiliriz. En kolayı write'a argüman olarak file'ı geçirmektir. Örneğin DOSYAM ile temsil edilen dosyaya yazmak için (DOSYAM print formatı kullanarak) şu ifadeyi kullanırız; write (DOSYAM);
Bu örnekte DOSYAM file adı ve format adı olarak kullanılıyor bu düzenli ve hoştur ama bazı kısıtlamaları vardır. Böyle bir durumda $~ kullanılamaz.(print format seçimi için). $~ sistem değişkeni default file değişkeniyle çalışır. O da write ile çıktıya gönderilir. default file variable'nı değiştirmek böylece $~ da etkin file'ı değiştirmek için hazır select fonksiyonu kullanılır.
select (DOSYAM);
Select kullanım için default file değişkenini set eder. Örneğin; file değişkeni DOSYAM ile temsil edilen, dosyaya yazmak amacıyla FORMATIM print formatını kullanmak için;
select(DOSYAM);
$~ = "FORMATIM";
write;
kodlamak gerekir. Bu kodlama ile FORMATIM formatı DOSYAM değişkeni ile birleştirilmiş oldu. Bundan sonra write artık bu dosyaya yazdırmaya başlar. Eğer tekrar standart çıktıya yazdırmak istersek
select(STDOUT);
komutunu kodlarız.
select kullanımı sadece write ' a değil print ' e de etki eder.
Select fonksiyonu çok kullanışlı olup aynı altyordamla aynı anda birden fazla dosyaya yazdırma imkanı sağlar. Örnek programda bunu görebiliriz.
1: #!/usr/local/bin/perl
2:
3: open (DOSYA1, ">dosya1");
4: $karakterler = "Denemeler";
5: select (DOSYA1);
6: &kayityaz;
7: select (STDOUT);
8: &kayityaz;
9: close (DOSYA1);
10:
11: sub kayityaz {
12: $~ = "KAYITYAZ";
13: write;
14: }
15:
16: format KAYITYAZ =
17: CIKTI DOSYALARIMA@<<<<< YAZIYORUM.
18: $karakterler
19: .
çalışması:
program.pl¿
CIKTI DOSYALARIMADeneme YAZIYORUM.
Yukardaki satır hem ekrana hem de dosya1 isimli dosyaya yazar.
select ve $~ rastgele kullanılmaz format takibini kaybedebiliriz. Aşağıdaki örnekteki gibi kullanım uygundur .
select (DOSYAM);
$~ = "FORMATIM";
write;