Home Map Index Search News Archives Links About LF
[Top bar]
[Bottom bar]
[Photo of the Author]
by Guido Socher

Yazar hakkında:

Guido uzun zamandır bir Linux bağımlısı ve Perl korsanıdır. Bu günlerde evini yenilemek ve bahçesinde bitki yetiştirmekle oldukça meşguldür.

İçerik:

Perl kısım II

[Illustration]

Abstract:

Perl kısım I Perl hakkında genel bir bakış sağlar. Perl kısım II'de ilk kullanışlı programımızı yazacağız.



 

Programınız için bir çatı

Perl en iyi bir soru üzerine özelleştirilmiş küçük progromlar yazmakta kulllanılır. Geliştirme işlemini hızlandırmak için bir çok programda olmasını isteyebileceğiniz temel yapı ve fonksiyon öneren bir çatıyı elde tutmak iyi bir fikir. Aşağıdaki kod templatetemel komut okuma satırı seçeneği önerir ve yardım mesajı yazdırmak için bir değişmeze sahiptir.

!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
# uncomment strict to make the perl compiler very
# strict about declarations:
#use strict;
# global variables:
use vars qw($opt_h);
use Getopt::Std;
#
&getopts("h")||die "ERROR: No such option. -h for help\n";
&help if ($opt_h);
#
#>>your code<<
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
print "help message\n";
exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

Kaynak koda bir bakalım. &getopts() komu satırı opsiyonunu okumak için Getopt::Std kütüphanesinden bir subroutine çağırır. Komut satırında sağlanan opsiyonlara göre $opt_<option> ismi değişkenlik gösterir. Komut satırındaki bütün opsiyonlar "-" (eksi işareti) ile başlar ve program isminden hemen sonra ve başka argüman girmeden hemen önce gelmelidir. (Not: bu genel bir Unix kuralıdır). amp;getopts (yukarıdaki programdaki "h") komut dizisi izin verilen bütün opsiyon harflerini listeler. Eğer opsiyon bir argüman alırsa o zaman opsiyon harfinden sonra iki nokta üstüste konulmalı. &getsopt("d:x:h"), bu program -d, -x and -h opsiyonlarına sahiptir demektir. -d ve -x opsiyonları bir argüman alırlar. Bu yüzden "-d birşey" doğru olur ama "-d -x birşey" -d'yi bir argüman izlemediği için yanlış olur.
Eğer komut satırınca -h opsiyonu verilmişse, $opt_h değişkeni kurulur ve &help if ($opt_h);sonuçta eğer -h opsiyonu komut satırında verilmişse değişmez help'i çağırır. sub help{ cümlesi değişmezliği açıklar. Şu anda kodun her detayını anlamanız çok önemli değil. Sadece sizin asıl fonksiyonunuzu ekleyebileceğiniz bir yer olan template olarak anlayın yeter.

 

Template kullanımı

Şimdi bu çatıyı kullanan küçük bir sayı çevirici yazalım. Program, ona numconv diyelim, altılık sayıyı ondalık sayıya çevirmeli veya tersini yapmalı.
numconv -x 30 ondalık 30'un altılık dengini yazdırır.
numconv -d 1A altılık 1A'nın ondalık dengini yazdırır.
numconv -h yardım metini yazdırır.
Perl fonksiyonu hex() altılık sayıları ondalık sayılara çevirir ve fonksiyon printf() ondalık sayıları altılık sayılara çevirmekte kullanılabilir. Bunu template'imize koymak bize güzel bir program oluşturur:

#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
# uncomment strict to make the perl compiler very
# strict about declarations:
#use strict;
# global variables:
use vars qw($opt_d $opt_x $opt_h);
use Getopt::Std;
#
&getopts("d:x:h")||die "ERROR: No such option. -h for help\n";
&help if ($opt_h);
if ($opt_d && $opt_x){
    die "ERROR: options -x and -d are mutual exclusive.\n";
}
if ($opt_d){
    printf("decimal: %d\n",hex($opt_d));
}elsif ($opt_x){
    printf("hex: %X\n",$opt_x);
}else{
    # wrong usage -d or -x must be given:
    &help;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
    print "convert a number to hex or dec.
USAGE: numconv [-h] -d hexnum
    umconv [-h] -x decnum

OPTIONS: -h this help
EXAMPLE: numconv -d 1af
\n";
    exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

Eğer yukarıdaki numconv programını download etmek istiyorsanız buraya tıklayın.
Sopnraki paragraflarda bu programa daha yakından bakacağız ve anlamaya çalışacağız.

 

If-ifadeleri

If-ifadeleri perl'de 2 şekilde uygulanır:
expr if (cond);
veya
if (cond) BLOCK [[elsif (cond) BLOCK ...] else BLOCK]

BLOCK süslü parantezler {}içine yazılan sayısal ifadedir. Bu örnekteki gibi yazabileceğiniz anlamına gelir:

printf("hello\n") if ($i);

if ($i == 2){
   printf("i is 2\n");
}elsif ($i == 4){
   printf("i is 4\n");
}else{
   printf("i is neither 2 nor 4\n");
}

Tıpkı C'deki gibi kısa yol operatöleri && ve || kullanılabilir.
printf("hello\n") if ($i);
aşağıdaki şekilde de yazılabilir;
($i) && printf("hello\n");
Özellikle "||" bizim templatemizde olduğu gibi konuşma diline oldukça iyi çevirir.
getopts("d:x:h")||öl "ERROR\n";
"Opsiyonu al veya öl". Fonksiyon öl() temel olarak çıkış tarafından takip edilen printf'e denktir. Bir mesaj yazdırır ve programı sonlandırır.
&getopts("d:x:h")||die "ERROR\n";
ifadesi ! işaretinin operatör değil de mantıksal bir ifade olduğu aşağıdaki ifadeye denktir;
die "ERROR\n"; if (! &getopts("d:x:h"));
Bu tekrar şöyle yazılabilir;
die "ERROR\n"; unless (&getopts("d:x:h"));
unless if-not'la aynı anlama gelir ve onu okumak if(!..) 'i okumaktan daha kolaydır. Gördüğünüz gibi perl'de if-ifadesi yazmanın birden fazla yolu var. Hepsini kullanmak zorunda değilsiniz. Sizin için en rahat olanını kullanın.

 

Değişkenler

İlk perl yazısında gördük ki sayısal değişkenler ($-değişkenleri) açıklanmadan kullanıldı. Onlar tam kullanıldıkları an var olurlar. Bu küçük programlar için hoş bir özellik ancak daha büyük programlarda bulması zor hatalar getirebilirler. Bir değişkeni açıklamak derleyiciye yazım hataları için fazladan kontrol yapma olanağı sağlar.
"use strict;" forces you to declare everything.
Aşağıdaki doğru kod örneğini inceleyiniz:

#!/usr/bin/perl
use strict;
my $i=1;
print "i is $i\n";

Bu program doğrudur ve "i is 1"i üretir. Şimdi düşünelim ki i yerine yanlışlıkla j yazdık:

#!/usr/bin/perl
#
$i=1;
print "i is $j\n";

Bu kod perl'de çalışır ve "i is "i üretir. Perl sabit değeri "use strict;" böyle bir program için derleyiciyi şikayet etmeye zorlayabilir. "strict"i kullandığınız zaman her şey tanıtılmış olmalı aksi takdirde bir hata mesajıyla karşılaşırsınız.

#!/usr/bin/perl
use strict;
my $i=1;
print "i is $j\n";

Bu aşağıdaki mesajın gelmesine neden olur ve yazım yanlışını kolayca görmenizi sağlar.


Global symbol "$j" requires explicit package name at ./vardec line 4.

Execution of ./vardec aborted due to compilation errors.

Exit 255

Değişkenler perl'de "my" kullanarak tanıtılabilir ya da daha önceden çatıda gördüğümüz gibi "use vars qw()" kullanarak da tanıtılabilir:
use vars qw($opt_h);

Geniş çaplı değişkenler use varsile tanıtılır. Bu değişkenler içerilen tüm kütüphanelerde de geniş çaplıdır.
Geçerli program dosyasına (bu dosyadaki tüm değişmezler arasında geniş çaplı olarak) yerleşen değişkenler programın başında (bir değişmezin dışında) myile tanıtılmalı.
Geçerli değişmeze yerleşen değişkenler myile değişmezin içinde tanıtılır.

Kabuk programlamada deneyimli insanlar bir değişkeni tanıtırken veya ona değer atarken $ işaretini unutmaya meyillidir. Bu perl'de mümkün değil. Sayısal değişken kullanırken daima $ işaretini yazın.

Ayrıca bir değişkeni tanıtırken ona direk bir değer atayabilirsiniz. my $myvar=10; $myvar değişkenini tanıtır ve onun ilk değerini 10 olarak koyar.

 

Değişmezler

Biz önceden "help" değişmezini yukarıdaki numconv programında kullanmıştık. Değişmezler sizin kendi fonksiyonlarınızın programında kullanılabilir. Programınızı yapılandırmanızda yardımcı olur.
Bir değişmez program metinindeki (önce ya da sonra çağırılır. Önemli değil) herhangi bir yerinin içine koyulabilir. Bir değişmeze sub name(){... ile başlarsınız ve $retval=&name(...arguments...) ile çağırırsınız. Dönüş değeri değişmezde son çalıştırılan ifadenin değeridir. Değişmeze verilen argümanlar değişmezin içindeki koda özel bir sırada @_ geçer. Bu konuya Perl III'de sıralardan bahsederken daha detaylı bakacağız. Şimdilik sayısal değişkenlerin değerinin değişmez içinde shiftkullanarak okunabildiğini bilmek yeterli. Burada bir örnek:

#!/usr/bin/perl
use strict;
my $result;
my $b;
my $a;
$result=&add_and_duplicate(2,3);
print "2*(2+3) is $result\n";

$b=5;$a=10;
$result=&add_and_duplicate($a,$b);
print "2*($a+$b) is $result\n";

# add two numbers and multiply with 2:
sub add_and_duplicate(){
    my $locala=shift;
    my $localb=shift;
    ($localb+$locala)*2;
}
 

Gerçek bir program

Şimdi birçok Perl sözdiziminde ve dilin elemanlarında yol aldıktan sonra,gerçek bir program yazmanın tam sırası!
Perl az bir programlama çabası ile metin dosyalarını işlemek için dizayn edilmiştir. İlk Perl programımız kısaltmaların listesini karşılaştırmalı, sonra da bu listedeki kopyaları bulmalı.Kopyalarla listede bazı zamanlar ortaya çıkan kısaltmaları kastediyoruz. Liste aşağıdaki gibi görünür:

It is easy to manipulate text files with Perl
AC Access Class
AC Air Conditioning
AFC Automatic Frequency Control
AFS Andrew File System
...

You can download the list here. The syntax of this file is:

Böyle bir metin dosyasını nasıl okumalı? Aşağıda, metni satır satır okumak için bazı Perl kodları verilmiştir:


....
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(){
   #do something
}
close FD;
....

Açık fonksiyon bir dosya betimleyicisini ilk arguman olarak, dosyanın adını da ikinci arguman olarak alır. Dosya betimleyicileri bazı özel değişken çeşitlerindendir. Siz sadece bunu açık fonksiyonun içine koyun, veriyi dosyadan okuyan fonksiyonda kullanın ve en sonunda da kapalı fonksiyona verin. Dosya <FD>ile okunur. <FD>. while döngüsüne arguman olarak verilebilir ve bu sonradan satır okuyucusuyla bir satırda sonlanır.
Genel olarak dosya betimleyicileri Perl'de üstel ifadeli harfler olarak yazılır.

Peki bu veri nereye gidiyor? Perl'ün birkaç örtük değişkenleri vardır.Bunlar sizin hiç ifade etmediğiniz değişkenlerdir .Onlar her zaman oradadırlar. Böyle bir değişken de $_ dir.Bu değişken genellikle üstteki while döngüsünde okunan satırı korur.Hadi şimdi deneyelim!( kodu yükle:

#!/usr/bin/perl
use strict;
my $i=0;
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(<FD>){
   # increment the line counter. You probably
   # know the ++ from C:
   $i++;
   print "Line $i is $_";
}
close FD;
The implicit variable $_ holds the current line.

Gördüğünüz gibi print "Line $i is $_\n"YAZMADIK.$_ değişkeni ,bulunan satırı, yeni satır komutu (\n)'i içeren metin dosyasından korur.

Şimdi dosyayı nasıl okumamız gerektiğini biliyoruz. Aslında programı tamamlamak için iki şey daha öğrenmemiz gerekiyor :

  1. Kısaltmaları satırın başından nasıl okuyacağımız
  2. Perl'ün karışık tablolarının nasıl çalıştığı

Düzenli Anlatım metin katarında bir örüntü aramak için sofistike ortalamalar sağlar. Biz ilk boşluktan itibaren bir satırdaki ilk katarı arıyoruz . Başka bir deyişle görüntümüz "satırın başı--birkaç karakter ama boşluk değil--bir boşluk"tur. Perl düzenli anlatımında bu ^\S+\stir. Eğer bunu bir m// içine koyarsak;Perl bu anlatımı $_ değişkenine atayacaktır (Hatırlatma:Bu değişken, bulunan satırı da tutuyordu!).\S+ düzenli anlatımlarda "bir kaç karaktere ama boşluk değil" karşılık gelir. Eğer \S+'in etrafına parantez koyarsak, $1 değişkeninde arkada "boş karakter değil"i alırız. Bunu kendi programımıza ekleyebiliriz:

#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
use strict;
# global variables:
use vars qw($opt_h);
my $i=0;
use Getopt::Std;
#
&getopts("h")||die "ERROR: No such option. -h for help.n";
&help if ($opt_h);
#
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(<FD>){
    $i++;
    if (m/^(\S+)\s/){
        # $1 holds now the first word (\S+)
        print "$1 is the abbreviation on line $i\n";
    }else{
        print "Line $i does not start with an abbreviation\n";
    }
}
close FD;
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
     print "help text\n";
     exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

Match operatörü(m/ /)eğer düzenli anlatım başarılı bir şekilde, bulunan satıra uygulanırsa 1'e döner . Bu yüzden bunu bir if ifadesinin içinde kullanabiliriz. $1'in gerçekten geçerli veriyi içermesini sağlamak için $1'i kullanmadan önce, match operatörünün etrafında her zaman bir if ifadesi kullanmalıyız.

   

Karışık Tablolar

Şimdi dosyayı okuyup ve kısaltmayı alabiliriz ve de bütün eksik olan bizim bu kısaltmaları daha önceden okuyup okumadığımızı görmek! Burada yeni bir perl veri tipine gereksinimiz var: Karışık Tablolar. Karışık tablolar bir katar tarafından indekslenebilen sıralardır. Bütün Karışık Tabloyu kastettiğinizde, değişkenin isminin önüne bir % işareti koyarız. Kişisel bir değer okumak istediğiniz zaman $variable_name{"index_string"} kullanırsınız. Aynı $'ı diğer değişkenler için olduğu gibi sadece normal bir skaler değişkenmiş gibi karışık tablonun içine alan olarak kullanabiliriz. İşte bir örnek:

#!/usr/bin/perl -w
my %htab;
my $index;
# load the hash with data:
$htab{"something"}="value of something";
$htab{"somethingelse"}=42;
# get the data back:
$index="something";
print "%htab at index \"$index\" is $htab{$index}\n";
$index="somethingelse";
print "%htab at index \"$index\" is $htab{$index}\n";

When running this program we get:

%htab at index "something" is value of something
%htab at index "somethingelse" is 42

Şimdi programımız tamamlandı:

 1  #!/usr/bin/perl -w
 2  # vim: set sw=4 ts=4 si et:
 3  # 
 4  use strict;
 5  # global variables:
 6  use vars qw($opt_h);
 7  my %htab;
 8  use Getopt::Std;
 9  #
10  &getopts("h")||die "ERROR: No such option. -h for help.n";
11  &help if ($opt_h);
12  #
13  open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n"; 
14  print "Abbreviations with several meanings in file abb.txt:\n";
15  while(<FD>){ 
16      if (m/^(\S+)\s/){
17          # we use the first word as index to the hash:
18          if ($htab{$1}){
19              # again this abbrev:
20              if ($htab{$1} eq "_repeated_"){
21                  print; # same as print "$_";
22              }else{
23                  # this is the first duplicate we print first
24                  # occurance of this abbreviation:
25                  print $htab{$1};
26                  # print the abbreviation line that we are currently reading:
27                  print;
28                  # mark as repeated (= appears at least twice)
29                  $htab{$1}="_repeated_";
30              }
31          }else{
32              # the first time we load the whole line:
33              $htab{$1}=$_;
34          }
35      }
36  } 
37  close FD; 
38  #
39  #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
40  sub help{
41          print "finddup -- Find abbreviations with several meanins in the
42  file abb.txt. The lines in this file must have the format:
43  abrev meaning
44  \n";
45          exit;
46  }
47  #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
48  __END__ 

Programı buraya basarak download edebilirsiniz.

Nasıl çalışır? Dosyayı satır satır okuduk ve satırları hash'ımızde yani %htab'da depoladık (line 33). Hashdaki dizin kısaltmadır. Hash'ı yüklemeden önce hash'da daha önceden yüklenmiş birşey var mı diye kontrol etmeliyiz(line 18). Eğer birşey varsa iki ihtimal vardır:

  1. Bu ilk kopyadır.
  2. Bu kısaltmada daha önceden birkaç kopya varmış

İki olayı birbirinden ayırdedebilmek için "_repeated_"katarını hash'ın içine, bizim dosyanın içinde çoktan bir kopya bulduğumuzu belirtmek için, yazarız (line 29).

Bu belki de kodu download edebilmek için en iyi yoldur Hadi bir sınayın!

 

Bir sonraki ne?

Bu makalede çoktan perl dilinin bazı detaylarını öğrendiniz. Henüz perl'ün sahip olduğu bütün veri tiplerini öğrenmediniz ve belki de yukarıdaki programımızda "abb.txt"dosya adının zor kodlanmasını engellemenin mümkün olup olmadığını merak ediyorsunuz. Siz çoktan bunu engellemek için nasıl bir opsiyon kullanmanız gerektiğini biliyorsunuz(e.g finddup -f abb.txt). Programı değiştirmeye çalışın!Komut satırını ve veri tipi sırasını okumanın genel yolu bir sonraki makalede verilecektir.


Web sayfaları LinuxFocus Editör takımı tarafından devam ettirilmektedir.
(c) Guido Socher
LinuxFocus 1999
en -> tr Gonca Akı & Hale Aslı Çalkaya

1999-11-06, generated by lfparser version 0.9