Pattern (string / kelime ) Örneği Bulma:(Pattern Matching)
Bilhassa dosyalarda tarama yaparken çok kullanılan bu işlemin kurallarını öğreneceğiz.
Pattern nedir ? : slash (/) karakterleri arasında bulunan karakter dizisidir.
Ör: /gazi/ Bu pattern gazi kelimesini temsil eder.
Pattern tarandığı bir satırda bulunduğunda uygun örnek bulunmuş olur. Biz şu ana kadar pattern bulma ile ilgili olarak
@array = split(/ /, $line); benzeri örnekler gördük. Burada / / boşluk karakterini temsil ediyor ve o amaçla aranıyordu.
Pattern bulmada kullanılan operatörler:
Bir karakter stringinde pattern parçası bulmak için özel operatörler vardır. patternin varlığını test eden operatör =~ operatörüdür.
Ör: $sonuc = $degisken =~ /abc/;
Bu komutla $degisken içinde(stringte) abc patterninin bulunduğu test edilir. Sonuç $sonuç değişkenine atanır. Sonuç ise
aşağıdakilerden biridir:
1- 0 olmayan değer veya true (doğru) --- pattern stringte bulundu ise ---
2- 0 veya false --- pattern stringte bulunmadıysa ---
1.sonucta $sonuc içeriği 0 olmayan bir değer,2.sonucta ise 0 değeridir.
!~ operatorü, =~, operatörüne benzer tek farkla ki bu operatör patternin bulunmadığını (olumsuz karşılaştırma) test eder.
Ör:
$sonuc = $degisken !~ /abc/;
Burada abc bulunmuşsa $sonuc değeri 0 dır.Bu tip kodlamalar özellikle şart ifadelerinde çok kullanılır.
Örnek program : Program adı pat1.pl
#!/usr/local/bin/perl
print ("Icinde Lutfen kelimesi olan bir soru cümlesi giriniz:\n");
$soruyual = ;
if ($soruyual =~ /lutfen/) {
print ("Istenilen kelimeyi girdiniz.Teşekkür ederim!!\n");
} else {
print ("Istenilen kelimeyi neden girmediniz?.\n");
}
Çalışması:
>pat1.pl
Icinde Lutfen kelimesi olan bir soru cümlesi giriniz:
Lutfen kapıyı açarmısınız?
Istenilen kelimeyi girdiniz.Teşekkür ederim!
>
PATTERNLERDE ÖZEL KARAKTERLER
+ KARAKTERLERİ KULLANIMI
önündeki(sol) karakterden 1 veya fazlası anlamındadır.
ör: /de+f/ patterni aşağıdakilerinden herhangi birini bulur.
def
deef
deeef
deeeeeeef
Not : + karakteri mumkun olduğunca önündeki karakterden 1 den fazla olanı bulur.
Ör : /ab+/ ,abbc stringini taradığında, bulduğu örnek abb dir ab değil.
+ kullanımı özellikle bir satırı kelimelere bölme gibi işlemlerde çok kullanışlıdır.
Örneğin bir satırda kelime aralarında bir veya birden fazla boşluk varsa ve bu boşluklardan kelime ayırımı yapacaksak + karakteri
kullanımı çok uygundur.
Ör : Girilen satırdaki kelimeleri sayan program yazalım. Satır girişi anında kelime aralarında 1 den fazla da boşluk bırakarak sonucu
görelim.
Program adı pat2.pl olsun.
#!/usr/local/bin/perl
$kelimesayisi = 0;
$satir = <STDIN>;
while ($satir ne "") {
chop ($satir);
@kelimeler = split(/ +/, $satir);
$kelimesayisi += @kelimeler;
$satir = <STDIN>;
}
print ("Toplam kelime sayısı: $kelimesayisi\n");
Çalışması:
>pat2.pl
Bu bir satır.
Bu başka bir satır.
Bu da son satır olsun.
^D
Toplam kelime sayısı: 12
>
[] KARAKTERİ KULLANIMI
Bu karakter bir alternatif gruptan bir karakteri tanımlamak için kullanılır.
Ör: /d[aA]f/ patterni daf ve dAf örneklerini bulur.
Bu kullanımda pattern içeriği daha fazla da olabilir.
Ör:/a[0123456789]e/ gibi..
Bu pattern a ile başlayan,onu takip eden bir rakam ve son karakter olarak e ile sonlanan örnekleri bulur. Daha evvel öğrendiğimiz +
karakterini de [] karakteri ile birlikte kullanabiliriz.
Ör: /a[cC]+f/
Bu pattern a ile başlayan,son karakteri f olan ve arada da bir veya birden fazla c ve C karakterleri olan örnekleri bulur.
Ör; acf
aCf
accf
aCcf
aCcCcf
Örnek Program : Adı pat3.pl. Önceki programda boşluk ve tab karakterini de düzenleyecek bir uygulama (kelimeler arsında bir veya
fazla boşluk ve tab kullanılabilir).
#!/usr/local/bin/perl
$kelimesayisi = 0;
$satir = <STDIN>;
while ($satir ne "") {
chop ($satir);
@kelimeler = split(/[\t ]+/, $satir);
$kelimesayisi += @kelimeler;
$satir = <STDIN>;
}
print ("Toplam kelime sayısı: $kelimesayisi\n");
Çalışması:
>pat3.pl
Bu bir satır.
Bu başka bir satır.
Bu da son satır olsun.
^D
Toplam kelime sayısı: 12
>
Bu örnekte bir öncekinden tek bir fark vardır split(/[\t ]+/, $satir); kodlaması. Bu kodlama ile $satir değişkeninde bulunan ekrandan
girdiğimiz satırda eğer kelimeler arasında bir veya birden fazla boşluk veya tab varsa bunların tümünü kelime ayıraç karakteri say ve
öyle değerlendir komutu vermiş oluyoruz.
* KARAKTERİ KULLANIMI
* karakteri önündeki karakterden bir veya fazla olduğunda veya hiç olmadığında geçerli örneği bulur.
Örneğin, /de*f/ paterni aşağıdaki örnekleri elde eder.
df (ilk karakter -d-, son karakter -f-,arada -e- yok)
def (ilk karakter -d-, son karakter -f-,arada 1 tane -e- var)
deef (ilk karakter -d-, son karakter -f-,arada 1 den fazla -e- var)
v.b...
Bu karakter,[] karakteriylede kullanılır.
Ör:/[eE]*/ gibi ..Bu pattern ile boş string ve e ile E karakterleri karışımı örnekler elde edilir.
? KARAKTERİ KULLANIMI
? karakteri önündeki karakterden bir tane veya hiç olmadığında geçerli örneği bulur.
Örneğin patternimiz şu ise, /de?f/ bu patternin elde edeceği örnekler, df ve def tir.Dikkat ediniz deef,uygun örnek değildir çünkü, ?
karakteri 1 taneden fazla karakteri kabul etmez.
BU TİP ÖZEL KARAKTERLER İÇİN ESCAPE DİZİSİ KULLANIMI
Perlde bulunan ve işlevi olan bazı karakterler ($,^,\, ..v.b.) pattern içinde nasıl kullanılır? Görelim.
Bu karakterleri kendi özellikleriyle kullanmak için pattern içinde önlerine bir \ karakteri konur veya \Q \E karakterleri arasında
kullanılır. mesela /\\+/ patterni stringte tüm \ karakteri (1 veya daha fazla) örneği olup olmadığını test eder.
/\$/ $ karakterini,
/\Q^ab*/ patterni, ^ab* karakterlerini,
/\Q^ab\E*/ patterni ise,^a ile bunu takiben b karakterini test eder.(yani
^a dan sonra b olan ve b olmayanlar(* dan dolayı-hatırlayınız- doğru örneklerdir).
HERHANGİBİR KARAKTER VE SAYI ÖRNEĞİ BULMA
/a[0123456789]c/
Bu pattern ilk karakteri a son karakteri c olan ve aralarındaki karakterde 0 ile 9 arası herhangi bir rakam olan örnekleri test eder.Bu
pattern daha kısa olarak şöyle de yazılabilir;
/a[0-9]c/
aynı işlevi görürler. Örneğin a1c,a5c,a9c doğru örneklerdir. Benzer şekilde ( 0-9 kullanımı) küçük ve büyük harflerde test edilebilirler.
Ör: /[a-z][A-Z]/, /[A-Z][A-Z]/, /[a-z][a-z]/, gibi..
ve rakam ve harfler birarada da test edilebilirler.
Ör: /[0-9a-zA-Z]/ gibi..([] arasındaki karakterlerden birisi varsa geçerlidir)
Örnek program : Basit bir değişken adı sınama programı. Program adı pat4.pl olsun.
#!/usr/local/bin/perl
print ("Bir değişken adı giriniz:\n");
$degisken = <STDIN>;
chop ($degisken);
if ($degisken =~ /\$[A-Za-z][_0-9a-zA-Z]*/) # skalar değişken olması için
# $ karakteri ile başlamalı,herhangi
# bir harf ve _ karakteri veya
# herhangibir harf veya rakam olmalı
{
print ("$degisken bir skalar değişkendir\n");
} elsif ($degisken =~ /@[A-Za-z][_0-9a-zA-Z]*/)# dizi değişkeni olması için
# @ karakteri ile başlamalı,herhangi
# bir harf ve _ karakteri veya
# herhangibir harf veya rakam olmalı
{
print ("$degisken bir dizi değişkenidir\n");
} elsif ($degisken =~ /[A-Za-z][_0-9a-zA-Z]*/) # dosya değişkeni olması için
# herhangi bir harf ile başlamalı,
# sonra _ karakteri veya
# herhangibir harf veya rakam olmalı
{
print ("$degisken bir dosya değişkenidir\n");
# Bu aşamada herhangibir değişken adı kuralına uymuyor demektir.
} else {
print (" $degisken değişken adı kurallarına uymuyor.\n");
}
Çalışması :
>pat4.pl
Bir değişken adı giriniz:
$soyad
$soyad bir skalar değişkendir
>
TAM ÖRNEĞİ BULMA
Yukardaki programda değişken adı olarak aşağıdakilerden
$soyad
ad$soyad
$soyad#atla
sonuçta /\$[a-zA-Z][_0-9a-zA-Z]*/ patterni $soyad'ı bulacaktır. Dolayısıyla istediğimizin tam gerçekleşmemiş olur. Çünkü doğru
örnek sadece 1.si ($soyad) olmalıydı.Tam olarak $soyad'ı bulsun istersek;yani sadece bu örnekte değil genelde tam örnek bulunsun
istersek;tam örnek bulma (Pattern Anchoring) karakterleri kullanırız.
Bunlar;
^ veya \A, Sadece string başından bul.
$ veya \Z, Sadece string sonundan bul.
\b, Kelime sınırlarında(Kelimenin başı veya sonu) bul
\B Kelime içinde bul.
karakterleridir.
Şimdi örneklerle daha iyi anlayacağız.
/^def/ sadece stringin en baştan ilk 3 karakteri def olanı bul.
/def$/ sadece stringin en sondaki 3 karakteri def olanı bul.
/^def$/ sadece def stringini bul.
Şimdi önceki programa (pat4.pl) daha iyi bir değişken adı test programı yazabiliriz.
Program adı pat5.pl olsun.
#!/usr/local/bin/perl
print ("Bir değişken adı giriniz:\n");
$degisken = <STDIN>;
chop ($degisken);
if ($degisken =~ /^\$[A-Za-z][_0-9a-zA-Z]*$/) {
print ("$degisken bir skalar değişkendir\n");
} elsif ($degisken =~ /^@[A-Za-z][_0-9a-zA-Z]*$/) {
print ("$degisken bir dizi değişkenidir\n");
} elsif ($degisken =~ /^[A-Za-z][_0-9a-zA-Z]*$/) {
print ("$degisken bir dosya değişkenidir\n");
} else {
print ("$degisken değişken adı kurallarına uymuyor.\n");
}
Çalışması:
>pat5.pl
Bir değişken adı giriniz:
5$soyad
5$soyad değişken adı kurallarına uymuyor.
>
KELİME SINIRLARINDA (kelimenin başında veya sonunda) TAM ÖRNEK BULMA: \b
Örnek:
Kelimenin başında :/\bert/ ert örneğiyle başlayan kelimeleri bulur.
Örneğin ert,ertan gibi kelimeleri bulur bertan bulunmaz.
Kelimenin sonunda :/ert\b/ kelimenin sonunda ert örneği olanları bulur.
Örneğin ert,mert kelimeleri bulunur ertan,bertan bulunmaz.
Şu örnekte ise sadece ert kelimesi bulunur. /\bdef\b/
Pekala şöyle bir soru aklımıza gelebilir.
kelimemiz $ertan olsaydı ,/\bert/ patterni ile bu ert kelimesi bulunurmuydu?
-Evet.
Çünki Enbaştaki $ karakteri stringin değişken olduğunu belirten karakter olup
dikkate alınmazdı.
KELİME İÇİNDE TAM ÖRNEK BULMA: \B
Bunu anlamak için yine örneklere bakalım.
/\Btan/ patterni, bulacağı örnek mesela ertan dır. tan kelimesinde test olumsuzdur.
Benzer şekilde /tan\B/ patterninde taner kelimesi aranan örneğe uyar
ve /\Btan\B/ pattern ine uyan örnekler mesela utanan,dartanyan olup.
tan,ertan,taner uymaz.
Bu karakterler (\b,\B) bize, bir kayıt(satır)dan ,split komutunu kullanmaksızın
kelime arama imkanını, sağlar.
Örnek Program : Bu kelimesini içeren satırların sayısını veren program.pat6.pl
#!/usr/local/bin/perl
$sayi = 0;
print ("Satırları Giriniz !:\n");
$satir = <STDIN>;
while ($satir ne "") {
if ($satir =~ /\bBu\b/) {
$sayi += 1;
}
$satir = <STDIN>;
}
print ("'Bu' kelimesi içeren satir adeti: $sayi\n");
Çalışması :
>pat6.pl
Satırları Giriniz !:
Bu birinci satır.
Bu ikinci satır.
Bu üçüncü satır.
Sondan önceki satır
Son satır.
^D
'Bu' kelimesi içeren satir adeti: 3
>
Bu örnekte bir satırda kaç adet Bu kelimesi olduğunu düşünmedik. Sadece Bu kelimesi var mı şeklinde test ettik.Bir satırda birden
fazla Bu kelimesi geçiyor ve biz kaç adet Bu geçtiğini bulmak istersek şu şekilde kodlama yapabiliriz.
if ($satir =~ /\bBu\b/) {
@kelimeler_dizisi = split(/[\t ]+/, $satir);
$say = 1;
while ($say <= @kelimeler_dizisi) {
if ($kelimeler_dizisi[$say-1] eq "Bu") {
$adet += 1; # kac adet Bu olduğu burada tutulur.
}
$say++;
}
}
veya daha kısa olarak şöyle de kodlayabiliriz.
if ($satir =~ /\bBu\b/) {
@kelimeler_dizisi = split(/\bBu\b/, $satir);
$adet += @kelimeler_dizisi - 1;
}
Hatta if kullanımına hiç gerek yoktur.
@kelimeler_dizisi = split(/\bBu\b/, $satir);
$adet += @kelimeler_dizisi - 1;
kodlaması yeterlidir. Çünkü satır otomatikman aranacaktır ve varsa Bu kelimesi yeni bir kelimeyi (dolayısıyla yeni bir dizi
elemanını)başlatan ayraç olacaktır. Dolayısıyla diziler 0.elemandan başladığından dizi boyutunun 1 eksiği bulunan kelime adedini
verecektir.
NOT : Pattern leri bir değişken içinde saklayarak,testlerde bu değişkenleri de kullanabiliriz.
Ör: $pattern = "[\\t ]+";
@kelimeler_dizisi = split(/$pattern/, $satir); .. gibi.
Örnek Program : Program Adı pat7.pl.İki dosyamız olsun.
Kullanacağımız dosyaların adları bilgi.dat ve alan.dat olup içeriği ise,
Bu ilk kayıttır.
İkinci kayit.
Dosyadaki son kayit.
şeklinde olsun.
Bu dosyaların adlarını komutsatırından girip,bir string 'i(pattern) bu dosyalarda taratalım.Taranacak string "kayit" olsun. Program
stringi bulduğu takdirde hangi dosyada ve hangi kayıtta (satırda) olduğunu ekrana bassın.
#!/usr/local/bin/perl
print ("Aranacak kelimeyi giriniz : ");
$aranankelime = <STDIN>;
chop ($aranankelime);
$dosya_adi = $ARGV[0];
$satirno = $bulunansayisi = 0;
while ($satir = <>)
{
$satirno += 1;
if ($satir =~ /$aranankelime/)
{
print ("$dosya_adi, satir $satirno\n");
@kelimeler = split(/$aranankelime/, $satir);
$bulunansayisi += @kelimeler - 1;
}
if (eof)
{
$satirno = 0;
$dosya_adi = $ARGV[0];
}
}
if ($bulunansayisi == 0)
{
print ("String bulunamadı !!! \n");
} else
{
print ("Bulunan $aranankelime kelimesi sayısı: $bulunansayisi\n");
}
Çalışması:
>pat7.pl alan.dat bilgi.dat
Aranacak kelimeyi giriniz : kayit
alan.dat, satir 2
alan.dat, satir 3
bilgi.dat, satir 2
bilgi.dat, satir 3
Bulunan kayit kelimesi sayısı: 4
>
HARİÇTE KALAN SEÇENEĞİ
Daha önce görmüştük ki [] karakterleri içindekilerden birisi aranırdı.
[ karakterinden sonra gelen ^ karakterinin([^) özel işlevi vardır ve kendisinden sonra gelen ve ] karakterine kadar olan karakterlerin
haricindekileri bulma (tarama) işlevi görür.
Örneğin, patternimiz /d[^eE]f/ ise, anlamı şudur;
ilk karakteri d sonraki karakter e veya E dışındaki bir karakter ve son karakter f olan örnekleri bul.
NOT:
Hatırlayalım; ^ karakterinin kendisi yalın olarak patterne dahil edilecekse,yani taranacak string içinde mevcutsa \ ile kullanırız.
Ör: /d[\^eE]f/ paterninin bulacağı örnekler mesela d^f, def, or dEf olacaktır.
ESCAPE DÜZENİNDE KULLANILAN KARAKTER DİZİLERİ TABLOSU
Daha evvel /a[1-3]c/ şeklinde kullanım örnekleri görmüştük. bu pattern de [1-3] şeklindeki kullanıma dikkatinizi çekiyorum. 1 ile 3
arası herhangi bir rakam anlamındaydı. Aynı mantıkla, /[0-9]/ ise 0 ile 9 arası bir rakam daha doğrusu herhangi bir rakam
anlamındaydı.
Şimdi inceleyeceğimiz konu buna benzer değişik bir kullanım şeklini öğrenmemizi sağlayacak.
mesela /[0-9]/ yerine aynı işlevi gören /\d/ patterni kullanacağız.
Önce bunları bir tablo halinde listeleyelim.
ESCAPE DÜZENİ
|
AÇIKLAMA
|
KARAKTER DİZİSİ
|
\d
|
Herhangi bir rakam
|
[0-9]
|
\D
|
Rakam olmayan karakter
|
[^0-9]
|
\w
|
Herhangi bir kelime karakteri
|
[_0-9a-zA-Z]
|
\W
|
Kelime karakteri olmayan
|
[^_0-9a-zA-Z]
|
\s
|
White space(Tab,Boşluk,v.b.)
|
[ \r\t\n\f]
|
\S
|
White space olmayan
|
[^ \r\t\n\f]
|
Bu durumda mesela /[\da-z]/ patterni rakam veya herhangibir küçük harfi test eder.
Pattern lerde kullanılan bir başka özel karakter . (nokta) karakteridir.
. karakteri pattern içinde herhangi bir karakteri temsil eder(yeni satır (\n) karakteri hariç).
Örneğin, /d.f/ patterninin test edeceği örnek; önce d, sonra (\n olmayan) herhangi bir karakter ve f dir.
def, d5f, d\tf gibi......
Nokta (.) karakteri sık sık da * karakteriyle kullanılır.örneğin, /d.*f/ patterninin bulacağı örnekler başta d sonda f içeren df arasında
\n harici herhangibir karakter veya karakterler den oluşan stringtir.* birden fazla olabilir anlamındadır ve ayrıca aradaki karakter
lerden en fazlasına sahip örneği bulur.
Ör: pattern /k.*a/ ise test edilen uygun örnekler ise kara,kona,karga,karavana ise bulunan string karavana olacaktır.
Perlde bulunacak örneklerdeki karakterleri istediğimiz adette olacak şekilde de buldurabiliriz(sınırlama).Sınırlandırmayı gerçekleştiren
karakterler {} karakterleridir.
Bir örnek verecek olursak; /de{1,3}f/ şeklinde kodladığımız pattern in anlamı şudur:
başta d en sonda f karakteri olacak arada da 1 veya 2 veya 3 adet e karakteri olacak. Bu durumda bulunacak örnekler şunlardır.def,
deef, ve deeef. Anlaşıldığı üzere df ve deeeeef gibi stringler değerlendirilmeyecektir.Tam karakter adetini de tabii ki verebiliriz.d ile f
arasında 3 adet e olan stringleri elde etmek istiyorsak, patternimiz şöyle tanımlanacaktır: /de{3}f/ .Ayrıca En az ve en fazla adette
olanları da buldurabiliriz.Örneğin,d ile f arasında en az 3 tane e olanları bulalım istiyorsak pattern tanımı: /de{3,}f/ şeklinde olur, En
fazla 3 tane e olacaksa tanımımız şudur:
/de{0,3}f/ burada başlangıç değeri 0 olarak kullanılmak zorundadır.
{} [] karakterlerini öğrendiklerimiz çerçevesinde birlikte de kullanabiliriz.
Ör: /[a-z]{1,3}/ paterni 1 veya 2 veya 3 küçük harf bulma işlevi görür.
/.{3}/ paterni ise 3 karakter bulur.
SEÇİM YAPMA KARAKTERİ: |
| karakteri kendisinin sağ veya solunda bulunan örneklerden birini seçme işlevi görür.
(veya anlamında)
Örneğin,
/def|ghi/ paterni def VEYA ghi stringini,
/[a-z]+|[0-9]+/ paterni ise 1 veya fazla küçük harf VEYA 1 veya fazla rakam bulur
matches one or more lowercase letters or one or more digits.
Örnek Program : Bu program basit bir tamsayı(decimal) geçerlilik programıdır.
Adı pat8.pl.
#!/usr/local/bin/perl
print ("Bir tamsayı giriniz:\n");
$number =<STDIN> ;
chop ($number);
if ($number =~ /^-?\d+$/) { # burada ^ ve $ tamsayı kontrulu için sınırlardır
# tamsayı bu karakterler arasında kontrol ediliyor
# - ve ? işareti negatif işaretinin varlığını
# \d+ ise 1 veya fazla rakamın varlığını test ediyor
print ("$number kurallara uygun bir tamsayıdır.\n");
} else {
print ("$number tamsayı değildir.\n");
}
Çalışması:
>pat8.pl
Bir tamsayı giriniz:
-135
-135 kurallara uygun bir tamsayıdır.
>
>pat8.pl
Bir tamsayı giriniz:
43.9
43.9 tamsayı değildir.
>
PATTERN BÖLÜMLERİNİN YENİDEN KULLANIMI
Aşağıdaki özelliklere sahip bir örneği test edecek pattern yazalım.
- 1 veya fazla rakam VEYA küçük harfler [\da-z]+
- onları takiben : veya ; karakterleri [:;]
- onları takiben 1 veya fazla rakam [\da-z]+
- onları takiben : veya ; karakterleri [:;]
- onları takiben 1 veya fazla rakam [\da-z]+
Yukardaki özellikleri içeren paternimiz
/[\da-z]+[:;][\da-z]+[:;][\da-z]+/ kodlamasıyla ifade edilebilir.
Burada [\da-z]+ ve [:;] pattern bölümlerinin tekrar edildiğini görüyoruz. Bu da kodlamayı ve incelemeyi zorlaştırdığı için perl daha
kısa bir yol sunmuştur.
Şöyleki yapılacak basit bir kodlama farkıyla tekrarlanan bu pattern bölümleri depolanır ve numaralanır.
Örneğin tekrarlanan ilk pattern ([\da-z]+) şeklinde belirlenir(hafızaya depolanır) (Aynı zamanda numarası 1 dir kodlaması ise \1
biçimindedir). Sonraki [\da-z]+ görülen yerlere \1 koyabiliriz artık. paternimizin yeni kodu hazırdır:
/([\da-z]+])[:;]\1[:;]\1/
Tekrarlanan [:;] bölümüne de aynı mantık uygulanırsa ( ([:;]) olarak depolanır. Numarası \2 dir) paternimizin son şekli belirlenmiş
olur: /([\da-z]+)([:;])\1\2\1/
Kısaca ilk ve son durumu karşılaştırmak amacıyla görelim.
İlk kodlama : /[\da-z]+[:;][\da-z]+[:;][\da-z]+/
Son kodlama : /([\da-z]+)([:;])\1\2\1/
Örneklerimiz de (genel de Perl de)bolca özel karakter kullandık ve daha sonra da kullanacağız.Karışıklılığa neden olmaması için
bunların kullanımlarına çok dikkat etmeliyiz.
Aşağıdaki pattern,
/\d{2}([\W])\d{2}\1\d{2}/
2 rakam,1 adet kelimede kullanılmayan karakter(Bunu hafızaya aldık),2 rakam ve tekrar kelimelerde kullanılmayan karakter ve tekrar
2 rakam örneğine uyar.Bu örneği tarih aratma için düşündüğümüzü varsayalım.Aşağıdaki örnekler bu patterne uyarlar:
12-05-92
26.11.87
07 04 92
aşağıdaki uymaz.
21-05.91 çünki . yerine - aranır.
Dikkat ettiyseniz \d{2} için hafızaya alma işlemi uygulamadık. Çünkü o takdirde ilk elde edilen 2 rakam diğerlerine de uygulanırdı ve
(örneğimizin tarih kontrolu olduğunu düşünürsek) tarih işlemlerinde sorun çıkardı.Gün değerinin,ay ve yıl ile aynı olanı geçerli örnek
olurdu. Biraz açarsak
/\d{2}([\W])\d{2}\1\d{2}/ ile
/(\d{2})([\W])\1\2\1/ aynı sonucu vermezler
2.örneğe uyan bir string 05-05-05 şeklinde olurdu 05-12-99 gibi değil.
$n hazır skalar değişkeni:
Özellikle ondalık noktalı patern işlemlerinde /-?(\d+)\.?(\d+)/ gibi paternler kullanacaksak \1 ,ilk (\d+) 'i temsil eder.Diğerine aynı
numara verilemez.Bu sorunu aşmak için hazır $n (n patern dizisini temsil eden rakamdır) özel değişkeni kullanılır.
Örneğin,
$string = "bu stringte şu sayı var 25.11.";
$string =~ /-?(\d+)\.?(\d+)/;
$tam = $1;
$ondalik = $2;
Bu kodlamayı incelersek, /-?(\d+)\.?(\d+)/ patterni 25.11 i bulur $1 ilk (\d+) yi $1 ikinci (\d+) yi temsil eder. 25 $1 de,11 ise $2 de
depolanır ve diğer değişkenlere atanır. Dikkat edilecek bir nokta da şudur:$1 ve $2 daha sonra başka patern işlemlerinde kullanılırsa
içerikleri değişeceğinden değerlerini başka değişkenlere atayarak kullanabiliriz.
Başka bir hazır skalar değişken: $&
Bu değişken /-?(\d+)\.?(\d+)/ patterninde tam patern örneğini saklar
Kısaca;
$string = "bu stringte şu sayı var 25.11.";
$string =~ /-?(\d+)\.?(\d+)/;
$sayı = $&;
kodlamasında $& içeriği 25.11 dir.
Pattern lerde kullanılan karakterlerde öncelik sırası:
1. ()
2. +,*,?,{}
3. ^,$,\b,\B
4. |
Örnek program : pat9.pl.Bu program tarih sınaması yapar. girilen tarihi sınar.Ayrıca 1900 lu yıllarda değilse 20.yy a ait değil mesajı
verir.
#!/usr/local/bin/perl
print ("YYYY-MM-DD formatında tarih giriniz:\n");
$tarih = <STDIN>;
chop ($tarih);
# Komplike olan bu değeri parçalara ayırıp
# skalar değişkenlere ve daha sonra yerlerine,
# koyalım.
# 31 günlük ay
$ay31 = "(0[13578]|1[02])\\2(0[1-9]|[12]\\d|3[01])";
# 30 günlük ay
$ay30 = "(0[469]|11)\\2(0[1-9]|[12]\\d|30)";
# Şubat ve artık yıl
$ay29 = "02\\2(0[1-9]|[12]\\d)";
# 20.asır (1900 lü yıllar)
$ornektarih = $tarih =~ /^(19)?\d\d(.)($ay31|$ay30|$ay29)$/;
# geçerli tarih ama 20.yy değil
$eskitarih = $tarih =~ /^(\d{1,4})(.)($ay31|$ay30|$ay29)$/;
if ($ornektarih) {
print ("$tarih geçerli bir tarih\n");
} elsif ($eskitarih) {
print ("$tarih 20.yy a ait değil\n");
} else {
print ("$tarih geçersiz bir tarih\n");
}
Çalısması:
>pat9.pl
YYYY-MM-DD formatında tarih giriniz:
1999-11-18
1999-11-18 geçerli bir tarih
>pat9.pl
YYYY-MM-DD formatında tarih giriniz:
2000-12-12
2000-12-12 20.yy a ait değil
>pat9.pl
YYYY-MM-DD formatında tarih giriniz:
1899-12-12
1899-12-12 20.yy a ait değil
>pat9.pl
YYYY-MM-DD formatında tarih giriniz:
1999-13-12
1999-13-12 geçersiz bir tarih
PATTERN BULMA SEÇENEKLERİ
Pattern örnekleri bulma işlemleri anında işimize yarar özellikler içeren bazı seçenekler kullanılır. Bunların tablosu aşağıdadır.
Tablo
Seçenek
|
İzah
|
g
|
Tüm örnekleri bul
|
i
|
Durumuna(case) aldırma
|
m
|
Stringi çoklu satırlı olarak kabul et
|
o
|
Sadece bir kez değerlendir
|
s
|
Stringi tek satırlı olarak kabul et
|
x
|
Pattern deki whitespace(boşluk,tab, v.b) lere aldırma
|
Tüm bu seçenekler patternin hemen ardından kodlanır. Örneğin i seçeneğini kullanacaksak /ab*c/i şeklinde kodlarız.Bu
seçeneklerden birden fazlasıda birarada kullanılabilir.Şimdi bu seçenekleri inceleyelim.
Mümkün olan tüm örnekleri bul /g seçeneği:
/g seçeneği patternin tüm örneklerini bulur.
Örneğin,pattern /.ta/g ise anlamı şudur.Aranan stringlerden, herhangi bir karakteri takiben ta ile devam eden varsa onları bul. Bu
durumda ata,eta,bal(ata),sal(ata) v.b uygun örneklerdir.
Örneğin aranan string salata ise ata örneği elde edilir. Yine patternimiz /.a/g ve stringimiz salata ise bulunan örnekler:sa,la,ta dır.
bunlar dizilere atanabilir ve kullanılabilirler.
Ör:
@dizi1 = "salata" =~ /.a/g; ise
@dizi1 dizi değişkeni içeriği (eleman listesi) şu şekildedir.("sa", "la", "ta")
Bu anlatımları isterseniz bir program halinde kodlayalım.
Program adı.pat10.pl olsun.
#!/usr/local/bin/perl
while ("salata" =~ /.a/g) {
$match = $&; #sistem değişkeni olan $& 'nın daima bulunan son pattern örneğini
# içerdiğini hatırlayınız.
print ("$match\n");
}
Çalışması:
>pat10.pl
sa
la
ta
>
Durumuna aldırma ( - case insensitive-) /i seçeneği:
Pattern de bulunankarakterlerin aranan stringte küçük veya büyük harf olmasına aldırmaksızın bulur.
Örneğin; /ve/i patterni ve, vE, Ve, or VE örneklerini bulur.
Coklu satırlı string /m seçeneği:
Bu seçeneği ifade eden /m kullanıldığında perl stringin birden çok satır içerdiğini kabul eder.^ karakteri string başlangıcını ya da yeni
satır başlangıcını bulur.
Ör: /^İkinci/m patterni ,
Önek satır\nİkinci satır başlangıcı stringinde
İkinci kelimesini bulur
Satır sonundaki kelimeleri de $ karakteri özelliğinden yararlanarak buluruz.
Ör:
/sonu.$/m patterni ile
Birinci satır sonu.\nDiğer satırın sonu.
satırındaki sonu. kelimeleri bulunur.
Patterni sadece bir defa değerlendir /o seçeneği:
/o seçeneğiyle bulunan pattern örneği bir defa değerlendirilir,işleme sokulur.
aynı pattern bulma satırı bir kaç defa daha işlense dahi ilk değerlendirilen
değer hala geçerlidir.
Ör
$var = 17;
while ($var > 0) {
$string = ;
$string =~ /abc/$var/o;
print ($string);
$var--; # yerleştirilen string hala 17 dir
}
Tek satırlı string /s seçeneği:
Önekle inceleyelim.
$string = "This is a\ntwo-line string.";
$string =~ s/a.*o/one/s;
# $string içeriği şu anda "This is a one-line string." tir.
m seçeneğini ^ ve $ ile kulanma örnekleri.
$string = "The The first line\nThe The second line";
$string =~ s/^The//gm;
# $string içeriği : "The first line\nThe second line"
$string =~ s/e$/k/gm;
# şu anda $string içeriği "The first link\nThe second link"
Pattern lerde White Space karakterleri kullanımı x seçeneği:
x seçeneği Perl'e ,stringlerde white space(\n,\t,\f,\r, ve boşluk) karakterlerine aldırmamasını söyler (önlerinde \ karakteri
olmadıkça)ve onları eler. $string =~ s/\d{2} ([\W]) \d{2} \1 \d{2}/$1-$2-$3/x patterni örneğinde gün-ay-yıl stringi dd-mm-yy
formatına cevrilir.
Diğer Ayraçlar:
Gördüklerimiz dışında başka ayraçlarda vardır.#,[,< gibi.
Bir örnek :
s#/u/bin#/usr/local/bin#
/u/bin yerine /usr/local/bin yerleştirir.
aynı işi aşağıdaki kodlamalar da yapar.
s(/u/bin)(/usr/local/bin)
s/\/usr\/local\/bin/
Çeviri operatörü :tr
Genel biçimi tr/string1/string2/ şeklindedir.string1 bulunur yerine string2 yerleştirilir.
Ör: $string = "abcdefghicba";
$string =~ tr/abc/def/;
kodlaması ile $string 'in son hali şudur: defdefghifed
Anlaşılacağı gibi a yerine d,b yerine e,c yerine f yerleşmiştir. Genelde küçük ve büyük harf çeviröelerinde kullanılır.
Örnek program : pat11.pl
#!/usr/local/bin/perl
while ($line =<STDIN> ) {
$line =~ tr/A-Z/a-z/;
print ($line);
}
Çalışması:
>pat11.pl
BÜYÜK HARFLE YAZIYORUM,KÜÇÜK HARFE DÖNÜŞTÜRECEK.
büyük harfle yazıyorum,küçük harfe dönüştürecek.
KArışıK Yazdım KÜÇÜK YAZACAK.
karışık yazdım küçük yazacak.
^D
>
Not : patern özel karakterlerinde bu dönüşümü sağlamak için tr yerine y kullanırız.
Ör : $string =~ y/a-z/A-Z/;
ÇEVİRİ OPERATÖRLERİ SEÇENEKLERİ
Çeviri operatörleri için 3 seçenek kullanılabilir.
Seçenek Anlamı
------- --------------------------------
c Tanımlı olmayan karakterleri seç
d Tanımlı tüm karakterleri sil
s Birçok aynı çıktı karakterinin , çıktı için sadece 1 tanesini seç
Ör:
$string =~ tr/\d/ /c;
ifadesi, rakam olmayan herşeyi ,bir boşluk olarak yerleştirir.
$string =~ tr/\t //d;
ifadesi, tanımlı her karakteri (tab ve boşluk),$string'ten siler.
$string =~ tr/0-9/ /cs;
ifadesi,rakam olmayan herşeyi,rakamlar arasında sadece 1 boşlukla çıktı olarak yerleştirir.
Örnek Program : Program adı:pat12 olsun.
#!/usr/local/bin/perl
$string =<STDIN> ;
$string =~ tr/0-9//cd;
print ("$string\n");
Çalışması:
>pat12.pl
Bu stringte 45 var.
45
>
Bu örnekte $string içindeki rakam olmayan karakterler seçilerek(c) silinmiştir(d).
Memory de saklamaksızın parenteze alma: ?:
Bu işlev için ?: karakterleri kullanılır.
Ör:
/(?:a|b|c)(d|e)f\1/
Bu örnekle şu işlemler yapılır,
a, b, veya c nin biri, a|b|c)
d veya e nin biri, (d|e)
f f
daha önce bulunan d veya e den biri \1
burada \1 in a|b|c değil (d|e) i temsil ettiği görülür.
Çünkü (?:a|b|c) paterninde bulunan ?: karakteri bu parentez içinin memoriye
saklanmasını önlemiştir.
Aşağıdaki ifadede ise \1 ile (a|b|c) temsil edilir.
/(a|b|c)(d|e)f\1/ kıyaslayarak anlayınız.
?? VE reset FONKSİYONLARI İLE PATTERN BULMA
?? operatörü // ile aynı işi görür ama döngü içinde ise sadece bir kez işler.
while ($satir =~ ?abc?) {
komutlar #?abc? pattern' i ikinci defa çalışmayacaktır.
}
eğer yeniden patterni kullanmak istersek reset fonksiyonuyla çağrılır. Bu durumu gösteren bir örnek
program aşağıdadır.
Örnek
#!/usr/local/bin/perl
while ($satir = <STDIN>) {
last unless ($satir =~ ?\bBu\b?);
print ("$satir");
reset;
}
çalıştır
>
Bu ilk satırdır.
Bu ilk satırdır.
Bu da sonraki satırdır
Bu da sonraki satırdır
Son satir.
>
NOT : reset fonksiyonu ayrıca adı tanımlanan karakterle başlayan tüm değişkenleri temizler(null).
örneğin; reset ("w"); kodu ile adının ilk karakteri w olan değişkenler içine null string atanır.
Ayrıca dizilere de uygulanır. Örneğin aynı mantıkla @wdizi isimli dizinin tüm elemanlarına null atanır.
reset ("ae"); -à a veya e ile başlayanları temizler
reset ("a-d"); -à a ile d arası hangisi olursa temizler
* çok dikkatli olunmalıdır.