|
Kalıp Tarama Ve İşleme Dili awk İle Linux'ta gawk Programlama (Bölüm II)
Okan Özeren okan.ozeren () students.comu.edu.tr
A. Murat Eren meren () comu.edu.tr
Düzenli ifadeler (regular expressions ya da regexp) belirli
katarları tanımlamanın bir yoludur. awk programlamanın önemli bir
parçası olan düzenli ifadelerin formatı ve kullanım şekilleri
ayrıca bir konudur.
29/08/2003 Adana, v.0.1b
BAŞLIKLAR
- BÖLÜM I (GİRİŞ-BAŞLANGIÇ)
- DÜZENLİ İFADELER (REGULAR EXPRESSIONS)
- Düzenli İfadeler Nasıl Kullanılır
- Karakter Kaçırma
- Düzenli İfade
Operatörleri
- gawk'ya Özel Regexp Operatörleri
- Eşleştirmede Büyük Harf-Küçük Harf
Hassasiyeti
- Ne Kadar Yazı Eşleştirilebilir?
- Dinamik Regexplerin Kullanımı
- BÖLÜM III (GİRDİ
DOSYALARININ OKUNMASI)
6. DÜZENLİ İFADELER (REGULAR EXPRESSIONS)
Düzenli ifadeler (regular expressions ya da regexp) belirli
katarları tanımlamanın bir yoludur. awk programlamanın önemli bir
parçası olan düzenli ifadelerin formatı ve kullanım şekilleri
ayrıca bir konudur.
Düzenli ifadeler, vi ve emacs gibi çoğu yazım işlemcilerinde,
grep/ egrep gibi programların içerisinde ve awk, perl, ve sed gibi
birçok dilde bulunabilir.
Düzenli ifadeler, ileri seviyede içeriğe duyarlı aramalarda
ve metin biçimlendirilmelerinde kullanılır. Bir düzenli ifade metin
şeritine karşı eşleştirilen bir modelin biçimsel bir
tanımlamasıdır.
Metin yazımı ve saatler alan arama işi birkaç saniye
içerisinde yapılabilir. Birkaç sözdizim kurallarını izlerler.
Her ne kadar düzenli ifadeler Unix dünyasında oldukça geniş
bir yayılıma sahipse de, "standart düzenli ifade dili" gibi birşey
yoktur. Bu daha fazla birkaç farklı lehçeye benzer. grep
programlarının örneğin iki çeşidi vardır; grep ve egrep. İkiside
azıcık farklı yetenekleriyle düzenli ifadeleri kullanır. Perl,
düzenli ifadelerin en eksiksiz kümesine sahiptir. Şansımıza, hepsi
benzer kuralları izler. Temel düşünceyi anladığınız zaman, farklı
lehçelerin detaylarını öğrenmek çok kolaydır.
Bölü (/) işaretleri arasında yazılan düzenli ifadeler ile
kayıttan süzülen veriler awk kalıbına göre seçilerek işlenirler. En
basit düzenli ifade ardışık harfler, sayılar veya her ikisidir.
Mesela regexp eşleştirmesi, herhangi bir katarı kapsar, ardışıktır.
Böylece, mesela 'sel' regexp'iyle eşleştirilen herhangi bir katar
'sel' katarını kapsamaktadır. /sel/ kalıbıyla eşleştirilen herhangi
bir girdi kaydı, kaydın içindeki herhangi bir yerde bu üç
karakterli katarı ('sel') kapsıyordur. Regexplerin diğer çeşidi de
sizin belittiğiniz, oldukça karmaşık katar sınıflarıdır.
Öncelikle basit regexp örnekleriyle başlayacağız.
Regexp'lerin çalışması hakkında geniş bilgiler vereceğimiz gibi çok
karmaşık işlemlerin oluşturulması hakkında da örnekler
sunacağız.
|
6.i Düzenli İfadeler Nasıl Kullanılır
Düzenli ifadeleri bölü karakterleri arasında bir kalıp gibi
kullanabilirsiniz. Regexp herbir kaydın bütün yazısına karşı
kontrol edilir. Örneğin aşağıdaki örnekte /er/ regexp'iyle
eşleştirilen, yani bu iki karakteri ardışık bir şekilde kapsayan
herbir kaydın ikinci alanı (sütunu) standart çıkışa yazılmaktadır.
Daha önceki bölümde kullandığımız telefon_listesi isimli veri
dosyasının içeriğini aşağıdaki gibi değiştirdik.
telefon_listesi
isim tarih saniye A:gündüz,B:gece,C:hafta_sonu
ali 2003/08/18 300 A
okan 2003/08/19 1200 B
murat 2003/08/21 650 A
ercan 2003/09/05 400 B
kemal 2003/07/20 100 A
erkan 2003/08/05 250 B
recep 2003/08/02 230 C
ertan 2003/07/04 550 B
sami 2003/09/01 400 C
halil 2003/08/05 450 B
ersen 2003/07/05 650 B
|
]# awk '/er/ { print "Tarih : "$2 }' telefon_listesi
Tarih : 2003/09/05
Tarih : 2003/08/05
Tarih : 2003/07/04
Tarih : 2003/07/05
|
Düzenli ifadeleri, istersek kayıt içerisindeki tüm satırla,
istersekte herhangi bir alanla karşılaştırma yapmak için
kullanabiliriz. '~' ve '!~', regexp için karşılaştırma olanağı
sağlayan iki operatördür. Bu operatörlerle kullanılan regexpleri,
kalıplar gibi veya if, while, for ve do ifadeleri içinde
kullanabiliriz.
ifade ~ /regexp/
Eğer belirtilen regexp eşleştirileceği sütunda varsa, o zaman
olumlu sonuç üretilir. Aşağıdaki eşleştirme veya seçme işlemi,
içinde küçük 'e' harfi bulunduran birinci sütun değerlerini
standart çıkışa yazar : (Burada, birinci bölümde verdiğimiz
ay_listesi isimli veri dosyası kullanılmaktadır.)
|
]# awk '$1 ~ /e/' ay_listesi
temmuz 15 425 0
eylul 30 500 1
ekim 60 525 1
|
Birde, aynı işlemi yapacak olan aşağıdaki kodu
deneyebilirsiniz :
|
]# awk '{ if( $1 ~ /e/ ) print }' ay_listesi
|
ifade !~ /regexp/
Eğer belirtilen regexp eşleştirileceği sütunda yoksa, o zaman
olumlu sonuç üretilir. Aşağıdaki eşleştirme veya seçme işlemi,
içinde küçük 'e' harfi bulundurmayan birinci sütun değerlerini
standart çıkışa yazar :
|
]# awk '$1 !~ /e/' ay_listesi
ocak 21 400 1
subat 21 425 2
mart 11 375 2
nisan 21 350 2
mayis 24 375 2
haziran 34 400 1
agustos 48 450 0
kasim 40 400 1
aralik 24 350 2
|
|
6.ii Karakter Kaçırma
Katar veya regexsp sabitleri, bazı karakterleri harfi harfine
kapsayamazlar. İşte bu özel karakterleri kaçırma karakteri ile
birlikte göstermek gereklidir. Ve bu yazım şekli, önde tersbölü (\)
sonrasında da kaçırılacak karakter ardışıklığıyladır.
Örneğin kaçırma karakterini, bir katar sabiti içerisinde çift
tırnak karakterini ekrana bastırmak istediğimiz zaman kullanmamız
gerekir. Bu işlem '\"' yazım şekliyle yapılır. Böylelikle, çift
tırnak karakterleri arasında yazılmış olan katar sabitini bölmeden,
bu karakteri de katara dahil edebilmemize imkan tanınmış olur.
Aşağıdaki gibi :
|
]# awk 'BEGIN{ print "Bu katar sabitinin içine \" karakterini, \\\" şeklinde karakteri kaçırarak yazabildik" }'
Bu katar sabitinin içine " karakterini, \" şeklinde karakteri kaçırarak yazabildik
|
Yukarıda da kullandığımız gibi eğer tersbölü (\) karakterini,
herhangi bir katar veya regexp sabiti içerisine yazmak istiyorsak o
zaman bir tersbölü karakteri daha kullanarak (\\) bu karakteri
kaçırabiliriz. '\' ve '"' karakterlerini ard arda kaçırmak
istiyorsakta yine yukarıdaki örnekte olduğu gibi "\\\""
kullanımıyla bu karakterleri kaçırabiliriz.
Başka bir kullanım şekli olarak, tab ve yenisatır
karakterleri gibi görünmeyen karakterleride ifade edebilmek için
tersbölü karakteri ile kaçırabiliriz. Bu tür karakterleri de, katar
ve regexp sabitleri içinde, bu yöntemle kullanabilmemiz mümkün
olmaktadır.
Aşağıdaki tabloda, kaçırılması gereken bütün karakterler
belirtilmekte ve açıklamaları da yanlarında yer almaktadır.
Karakterleri, katar ve regexp sabitleri içinde uygulamaya çalışıp
not almanızı öneririm.
\\ Tersbölü karakteri, `\'.
\a "alarm" karakteri, Control-g, ASCII kodu 7 (BEL).
\b Backspace karakteri, Control-h, ASCII kodu 8 (BS).
\f Formfeed karakteri, Control-l, ASCII kodu 12 (FF).
\n Newline (yenisatır) karakteri, Control-j, ASCII kodu 10 (LF).
\r Carriage return (satırbaşı) karakteri, Control-m, ASCII kodu 13 (CR).
\t Horizontal (yatay) tab karakteri, Control-i, ASCII kodu 9 (HT).
\v Vertical (dikey) tab karakteri, Control-k, ASCII kodu 11 (VT).
\nnn Sekiz tabanında (octal) bir değer olan nnn, `0' ve `7' arasında üç tane rakamdan oluşur. Örneğin,
ESC (escape) kaçırma karakteri nin ASCII kodu '\033'.
\xhh... Onaltı tabanında (hexadecimal) bir değer olan hh, `0' ve `9' arasındaki bir rakam veya `A' ve `F'
(`a' ve `f''de olabilir) arasındaki harflerden oluşabilir. ANSI C'de de aynı yapıya sahiptir.
Kaçırma karakterinden sonra ki ilk gelen karakter olan 'x' karakteri sayını onaltılık düzende
olduğunu belirtmektedir. Bununla birlikte ikiden fazla onaltı tabanında sayı belirtilirse, o zaman
tanımsız olarak algılanacaktır. (`\x' kaçırmasını POSIX awk sağlamaz.)
\/ Bölü karakteridir (yalnız regexp sabitleri için gereklidir). Bölü karakterini içeren bir regexp sabiti
kullanırsak bölü karakterini bu şekilde kaçırabiliriz. regexp'ler bölü karakteri ile sınırlandırıldığından,
bölü karakterini kalıbın parçası olarak kullanabilmek için bölü karakterini kaçırmak gereklidir.
\" Çift tırnak karakteridir (yalnızca katar sabitleri için gereklidir). Bunu, katar sabitleri arasında
çift tırnak karakterini kullanacağımız zaman uygulayabiliriz. Katar'ler çift tırnak karakteri ile
sınırlandırıldığından, çif tırnak karakterini kalıbın parçası olarak kullanabilmek için bu karakteri
kaçırmak gereklidir.
gawk'de, ilaveten regexp'lere özel, tersbölü ile başlayan
daha başka karakterler de vardır. Bunlara ilerde değineceğiz.
Peki, katar sabitlerinde, yukarıda listelenmemiş
karakterlerden birisi kullanılırsa ne olacaktır? POSIX awk, bu
durumda o karakteri kaçırmayacaktır. Bunun için iki seçenek vardır
:
- Tersbölüyü, listenin dışındakilerle kulanmak. Bunu UNIX awk ve
gawk yapar. Örneğin "a\qc" ile "aqc" katarlarının ikisi de aynı
çıktıyı verir. (Bu basit bir hatadır ve böyle bir kullanımda gawk
bizi uyaracaktır.) Düşünelim ki alan ayıracını şu şekilde
'FS="[\t]+\|+[\t]"', yani iki tane tab karakteri arasında boru
işareti olarak tanımladık. Bu tanımlama ile boru işaretini
belirtebilmek için iki tane tersbölü karakterini
'FS="[\t]+\\|+[\t]"' şekliyle kullanmamız gereklidir.
- Tersbölüyü tek başına kullanmak. Bunu bazı diğer awk'ler yapar.
Eğer "a\\qc" şeklinde kullanırsak o zaman çıktı "a\qc" katarı
olacaktır.
regexp içinde, yukarıdaki listede tersbölüden sonra
kullanılan ve gawk'nın tanıdığı özel regexp operatörleri içinde
bulunmayan bazı karakterleri kullanırken, bunların önüne tersbölü
karakteri getirdiğimizde awk bunu tersbölü karakteri yokmuş gibi
algılayacaktır. Örneğin, /a\+b/ ifadesi "a+b" üç karakteriyle
eşleştirilecektir.
Tamamiyle uyumlu bir program oluşturmak için listelenmemiş
karkterlerden önce tersbölü karakterini kullanmamalıyız.
Regexp metakarakterlerini gösteriren octal ve hexadecimal
kaçırma kullandığımızı farz edelim. awk, bu karakterleri regexp
operatörümü yoksa karakter olarakmı algılayacaktır?
Daha önce, karakterlerin harfi harfine alındığını görmüştük.
Bununla beraber POSIX standartlarında, o karakterler gerçek
metakarakterler olarak algılanacaktır (gawk'da ne yapıyorlarda o
işi yapacaklardır). Compatibility (uygun) modda (Komut satırı
parametrelerine bakınız), octal ve hexadecimal kaçırmaları regexp
sabitleriyle kullanıldığında, gawk, bu octal ve hexadecimal
sayılara karşılık gelen karakterleri algılayacaktır. Örneğin,
/a\52b/ ifadesi, /a\*b/ ifadesine ya da /\x65\x72/ ifadesi, /er/
ifadesine karşılık gelecektir.
Özetleyecek olursak :
- Yukarıda listelenmiş kaçırma karakterleri katar ve regexp
sabitleri için herzaman ilk işlenir. Bu, awk'nin programınızı
okuması kadar çok erken meydana gelir.
- gawk, regexpe özel operatörler için regexp sabitleri ve dinamik
regexplerin her ikisini de işler.
- Tersbölü (kaçırma karakteri) herhangi diğer bir karakterden
önce kullanıldığında sadece bu karakter algılanacaktır.
|
6.iii Düzenli İfade Operatörleri
Aşağıda metakarakter tablosu bulunmaktadır. Bu karkterleri
regexplerin içinde kullanmak için kaçırma karakteri kullanmaya
gerek yoktur.
\ Özel karakterlerin eşleştirilmesi yapılacakken bu operatör kullanılır. Örneğin:
\$
$ karakterinin eşleştirilmesi yapılmaktadır.
^ Bu operatör ile belirtilmiş katar, alanın başından itibaren aranacaktır. Örneğin :
^@bas
"@bas" katarı alanın başında aranır. Önemli bir nokta da bu karakterin başka bir kullanım
şeklidir. if() kalıbı içinde bir kontrol yapılacağı zaman kullanılmasına örnek olarak :
if( "satır1\n\SATIR2" ~ /^S/ ) ...
Burada "satır1\n\SATIR2" katarı 'S' karakteri ile başlıyorsa doğru yoksa yanşlış sonuç
üretilecektir.
$ Bu operatör bir önceki operatörün tam tersi olarak iş görür. Örneğin :
son$
"son" katarı alanın sonunda aranır. Yine if() kalıbı içinde bir kontrol yapılacağı zaman
kullanılmasına örnek olarak :
if( "satır1\n\SATIR2" ~ /1$/ ) ...
Burada "satır1\n\SATIR2" katarı '1' karakteri ile bitiyorsa doğru yoksa yanşlış sonuç
üretilecektir.
. Nokta operatörü, yerine herhangi bir karakter gelebileceğini belirtir. Örneğin :
.P
Bu ifade ile herhangi bir karakter ve sonra 'P' karakteri olan iki karakterli katarlar
eşleştirmeye uyar. Mesela "U.A" ifadesi ile 'U' ile başlayan, sonra herhangi bir karakter
olan ve sonunda da 'A' karakteri olan üç karakterli katarlar ifade edilir. POSIX modunda
'.' operatörü NULL karakterle eşleştirilmez.
[...] Bu operatör karakter listesini çağırır. Köşeli parantez ile kapalı bu ifade içindeki karakterler
birer birer eşleştirilir. Örneğin :
[MVA]
İfadesi ile katar içinde 'M','V' veya 'A' karakterlerinden herhangi biri aranır.
Bu operatörle bir aralık belirtilmek sureti ilede eşleştirme yapılabilir.
[0-9]
İfadesi 0 ile 9 aralığındaki bütün rakamlar için tek tek eşleştirme yapar.
(0 ve 9 dahil)
Çoklu aralık belirterekte eşleştirme yapılabilir.
[A-Za-z0-9]
İfadesinde bütün büyük ve küçük harfler ve 0-9 aralığındaki sayılar eşleştirilir.
'\', ']', '-' veya '^' karakterlerini eşleştirmede kullanmak istersek, o zaman onları,
önlerine \ karakteri koyarak kaçırmamız gerekmektedir. Örneğin :
[B\]]
İfadesinde 'B' ve ']' karakterleri eşeleştirme için kullanılacaktır.
Mesela aşağıdaki gibi, POSIX standartlarına uyan özel karakter sınıflarınıda kullanarak
eşleştirme yapabilmemiz mümkündür. Bu sınıfları "[:" ve ":]" ifadeleri arasında yazarız.
[:alnum:] Alfanümerik karakter
[:alpha:] Alfabetik karakter
[:blank:] Boşluk veya tab karakteri
[:cntrl:] Kontrol karakterleri
[:digit:] Nümerik karakterler
[:graph:] Ekrana basılabilir ve görünen karakterler (mesela boşluk görünemez)
[:lower:] Küçük alfabetik karakterler
[:print:] Ekrana basılabilen karakterler (Kontrol karakterleri değil)
[:punct:] Noktalama karakterleri (harfler, rakamlar, kontorl kar. ve boşluk kar. değil)
[:space:] Boşluk karakterleri (boşluk, tab, formfeed vs. gibi)
[:upper:] Büyük alfabetik karakterler
[:xdigit:] Karakterlere karşılık gelen hexadecimal sayılar
Karakter listesinde ortaya çıkan iki özel nokta daha vardır :
- Sembolleri Karşılaştırarak Okuma
'[.' ve '.]' aralığında çoklu karakter karşılaştırılmaktadır. Örneğin :
'ch' karşılaştırılacak eleman olsun, [.ch.] regexp eşleştirmesi ile 'c' veya 'h' karakterlerinin
olduğu alanlar eşleştirmeye uyar.
- Sınıflara Eşitleme
Yerel karakter listeleri için eşleştirme yapılır. '[=' ve '=]' aralığında belirtilir. Örneğin :
'e' karakteri kullanıldığında "e,", "è" ve "é" harfleri ile de eşleştirme yapılacaktır.
[=e=] regexp eşleştirilmesi "e", "è" ve "é" harflerini de içeren alanlarıda alacaktır.
Bu şekiller İngilizceden farklı bir dilde çok faydalı olabilir (Mesela ikinci kullanım, Fransızcada).
[^ ...] Bu operatör, ... ile belirtilen karakterler haricinde eşleştirme yapar. Örneğin :
[^0-9]
ifadesi içinde rakam bulunmayan alanlarla eşleştirilir.
| Bu operatör ile birbirini takip eden ifadeler kullanılabilir. Örneğin :
^P|[0-9]
ifadesi ile 'P' karakteri ya da 0-9 aralığındaki herhangi bir rakam ile başlayan alanlar
eşeleştirmeye uyar.
(...) Bu operatör regexler içinde gruplama yapmak için kullanılır. Bu operatör içindeki ifadeleri
'|' işareti ile birbirlerinden ayırıp sıralayarak kullanabiliriz. Örneğin :
`(er|ok)'
ifadesi ile "er" veya "ok" ile başlayan alanlar eşleştirilecektir.
* Bu operatör, önündeki karakterlere göre işlem yapar. Çoğu zaman tekrarlanmış karakterleri bulmak
için kullanılır. Örneğin :
er*
ifadesi 'e' ve onu takiben 'r' karakterlerini bulunduran, ayrıca sadece 'e' karakterlerini de bulunduran
alanları eşleştirir. Yani, alanda 'e' harfi yoksa 'r' harfinin bulunması birşey ifade etmez. Örneğin :
kan*
ifadesindeki gibi üç tane karakter belirttiysek, o zaman operatör "ka" katarını veya "kan" katarını
bulunduran ifadeleri eşleştirecektir. Mesela :
awk '/\(c[ad][ad]*r x\)/ { print }' veri
ifadesinde awk, "(car x)", "(cdr x)", "(cadr x)" ve "(caar x)" katarlarını bulunduran katarları
eşleştirecektir. Bu ifade de parantezlerden ( '(' ve ')' ) önce '\' karakterini kullandığımıza
dikkat ediniz.
ca*t
ifadesinde ise "ct", "cat", "caat", "caaat", ... gibi katarları bulunduran alanlar eşleştirmeye
uyar.
+ Bu operatör '*' operatörüne benzerdir, fakat önündeki karakterin en az bir kere eşleştirilmesi şarttır.
ca+t
ifadesinde 'a' karakterini en az bir veya birden fazla ard arda bulunduran, bu harfin önünde de 'c'
harfi bulunan ve ardında da 't' harfi bulunan alanlar eşleştirmeye uyar. Mesela "cat", "caat", "caaat", ...
gibi katarları bulunduran alanlar eşleştirmeye uyar ancak "ct" katarını bulunduranlar uymayacaktır.
Eğer "ca*t" ifadesini kullanmış olsaydık o zaman "ct" katarını bulunduran alanlarda eşleştirmeye
uyacaklardı.
awk '/\(c[ad]+r x\)/ { print }' veri
ifadesi "awk '/\(c[ad][ad]*r x\)/ { print }' veri" ifadesiyle aynı sonucu verecektir.
? Bu operatör de '*' operatörüne benzerdir, fakat bunda da operatörün önündeki karakterden en fazla bir
tane olması gerekmektedir. Örneğin :
ca?t
ifadesinde 'a' harfini bir kere bulunduran veya hiç bulundurmayan ifadelerler eşleştirme yapılır.
Mesela "ct" ve "cat" katarlarını bulunduran alanlar bu eşleştirmeye uyarlar.
{n}
{n,}
{n,m} Operatörleri önceki üç operatöre benzemektedir. Bu operatörlerle önüne gelen karakterin tekrar edilme
miktarları belirtilerek eşleştirme yapılır. Örneğin :
ca{3}t ifadesiyle "caaat" katarını bulunduran alanlar eşleştirilir. "cat",
"caaaaat", ... gibi katarları içeren katarlar eşleştirilmez. Yani
sadece üç tane 'a' bulunduran anlamındadır.
ca{2,4}t ifadesiyle sadece "caat", "caaat" ve "caaaat" katarlarını bulunduran
alanlar eşleştirilir. Yani iki ile dört arası mitarda 'a' bulunduran
anlamındadır.
ca{2,}t ifadesiyle ise "caat", "caaat", "caaaat", ... gibi katarları bulunduran
alanlar eşleştirilir. Yani iki veya daha fazla mitarda 'a' bulunduran
anlamındadır.
Aralık ifadeleri standart awk'de mevcut değildir. Birbirine uyumlu olarak birlikte çalışabilen
awk ve egrep beraberce POSIX standartları parçası olarak kullanılabilmiştir.
Aralık ifadelerini, öntanımlı gawk programlarında kullanırsak eşleştirme yapılmayacaktır.
regexp'lerde bu aralık ifadeleri kullanılarak eşleştirme yapılabilmesi için gawk'de
'--posix' veya '--re-interval' parametrelerini kullanmamız gerekmektedir. Örneğin :
gawk --posix '/ca{2,4}t/' veri
gawk --re-interval '/ca{2,4}t/' veri
Düzenli ifadelerde '*', '+' ve '?' operatörleri '{' ve '}'
operatörlerine göre yüksek önceliklidir ve son olarakta '|'
operatörü gelir. Fakat prantezler ( '(' ve ')' ) kullanıp gruplama
yapılarak bu öncelikler değiştirilebilir.
|
6.iv gawk'ya Özel Regexp Operatörleri
GNU yazılımları regexpler ile iş yapılırken ek regexp
operatörleri sağlarlar. Aşağıdaki operatörler sadece gawk'ya
özgüdür ve diğer awk yorumlayıcılarında mecvut değildirler.
Çoğu operatör kelime eşleştirme işlemleri ile ilgilidir.
Bizim amacımız, bir veya birden çok harf, rakamlar veya alt çizgi
('_') içeren kelimeleri eşleştirmektir.
\w Bu operatör ile herhangi bir harf, rakam veya alt çizgi içeren kelimeler eşleştirilir. Aynı işlemi
yapan [[:alnum:]_] yerine daha pratik bir kullanım sunar.
\W Bu operatör ile herhangi bir harf, rakam veya alt çizgi içermeyen kelimeler eşleştirilir. Bu operatörde
aynı işlemi yapan [^[:alnum:]_] yerine daha pratik bir kullanım sunar.
\< Bu operatörün ardında belirtilen katarla birebir eşit olan alanlar eşleştirmeye uyar, fakat sonunda
bulunduran alanlar eşleştirmeye uymaz. Örneğin :
/\<lik/
ifadesinde "lik" katarı eşleştirmeye uyar ama "kalemlik" katarı uymaz.
\> Bu operatörden önce belirtilen katarla birebir eşit olan alanlar eşleştirmeye uyar, fakat başında
bulunduran alanlar eşleştirmeye uymaz. Örneğin :
/\<kalem/
ifadesinde "kalem" katarı eşleştirmeye uyar ama "kalemlik" katarı uymaz.
\y Başta ve sonda kullanılmasına göre sonuç değişir. Eğer seçim katarının başında kullanılırsa o zaman
baştan itibaren bu katarı barındıran alanlar, eğer seçim katarının sonunda kullanılırsa o zaman
sondan itibaren bu katarı barındıran alanlar eşleştirmeye uyarlar. Örneğin :
/\ysayı/
ifadesiyle "sayı", "sayılar", ... gibi alanlar,
/lar\y/
ifadesiyle "lar", "sayılar", ... gibi alanlar,
/\ysayı?\y/
ifadesiyle ise hem "say" hemde "sayı" ifadesine denk alanlar eşleştirmeye uyarlar.
\B Bu operatörün de işlevi başta ve sonda kullanılmasına göre değişir. Eğer seçim katarının başında
kullanılırsa, başı hariç başka herhangi bir yerinde bu katar bulunan veya seçim katarının
sonunda kullanılırsa, sonu hariç başka herhangi bir yerinde bu katar bulunan alanlar
eşleştirmeye uyarlar. Eğer seçim katarı bu operatörün ikisi arasında yazılmışsa o zaman da başında
ve sonunda bu katar bulunmayan alanlar eşleştirmeye uyarlar. Örneğin :
/\Bklav/
ifadesiyle "oklava", "baklava", ... gibi alanlar eşleştirmeye uyar, fakat "klavye", ... gibi
alanlar uymaz,
/cere\B/
ifadesiyle "cereyan", "cereme", ... gibi alanlar eşleştirmeye uyar, fakat "tencere", ... gibi
alanlar uymaz,
/\Bkal\B/
ifadesiyle ise "tokalı", "bakalit" ... gibi alanlar eşleştirmeye uyar, fakat "kalfa", "bakkal", ...
gibi alanlar ve "kal" alanı eşleştirmeye uymazlar.
Ayrıca, tamponlar (buffer) üzerinde işlem yapan iki tane daha
operatör vardır. Emacs'te kullanılan tamponlar Emacs tamponlarıdır.
Fakat diğer programlar için, regexp işlemleri, mesela gawk'yi
düşünecek olursak girilen katarın eşleştirilmesi tamponda
yapılır.
awk için '^' ve '$' operatörleri her zaman katarın başı ve
sonuyla işlem yaparlar. Bu operatörler ek yeni yetenekler
getirmezler. Sadece diğer GNU yazılımlarına uyum sağlayabilmesi
içindir.
\` Bu operatör tamponun başındaki boş katarları eşleştirir.
\' Bu operatör tamponun sonundaki boş katarları eşleştirir.
Diğer GNU yazılımlarında '\b' (boundary) sınır operatörüdür,
fakat farklı olarak gawk'de ve diğer awk yorumlayıcılarında '\b'
karakteri geriboşluk (backspace) olarak tanımlanmıştır.
Birkaç komut satırı parametresi ise gawk'de regexp'ler
içindeki bazı karakterlerin nasıl yorumlanması gerektiğini
belirtir.
Parametre yoksa
Öntanımlı seçenekte gawk, bütün POSIX regexplerinin sağladığı imkanları ve yukarda tanımlı
GNU regexp operatörlerini sağlar. Bunula birlikte aralık ifadelerini desteklemez.
--posix
Yalnızca POSIX regexpleri sağlanır, GNU operatörleri geçersiz olur (mesela, '\w' operatörü
'w' harfi olarak algılanır). Aralık ifadeleri de desteklenir.
--traditional
Standart Unix awk regexpleri eşleştirilir. GNU operatörleri, aralık ifadeleri ve POSIX karakter
sınıfları ([[:alnum:]] ve diğerleri) desteklenmez. Karakterler, o karakter yerine geçen octal
ve hexadecimal kaçırma ifadeleri ile tanımlanmıştır. regexp metakarakterlerini gösteriyorlarsa
bile.
--re-interval
regexplerde aralık ifadelerine izin verilir, hatta `--traditional' sağlanmışsa bile.
|
6.v Eşleştirmede Büyük Harf-Küçük Harf
Hassasiyeti
Seçim genellikle, alışılmış karakterler eşleştiriliyorken
(metakarakterler değil) regexpler içinde anlamlıdır. Bunun için
'w', düzenli ifadenin içinde 'w' karakteri ile eşleştirilirken 'W'
karakteri ile eşleştirilmez.
Bu eşleştirme hatasına düşmemek için istenilen karakterler
liste olarak verilebilir. '[Ww]' listesini belirtmek işimizi
oldukça kolaylaştıracaktır. Fakat sık sık bu hantal kullanımı
uygularsak regexp ifadelerinin okunmasını çok zorlaştırabiliriz.
Bunun yerine tercih edebileceğiniz iki alternatifiniz
bulunmaktadır.
Birinci yol, alanlardaki alfabetik karakterleri büyük veya
küçük harflerine çevirebilen fonksiyonları kullanmaktır. Örneğin
:
tolower($1) ~ /sel/ { ... } # eşleştirmeden önce 1. alandaki karakterleri küçük yapar
toupper($1) ~ /sel/ { ... } # eşleştirmeden önce 1. alandaki karakterleri büyük yapar
Bu bütün POSIX awk'lerle uyumludur.
Diğer yolsa gawk'ye özel bir değişken olan IGNORECASE
değişkeniyle ilgilidir. Bu metodda IGNORECASE değişkenine sıfırdan
farklı bir sayı atarsak gawk, bütün regexp ve katar işlemlerinde
büyük-küçük harf ayrımı yapmayacaktır. Eğer IGNORECASE değişkenine
sıfır değerini atarsak gawk büyük-küçük harf ayrımı yapacaktır.
IGNORECASE değişkenine programın çalışma zamanında atama
yapabiliriz. Bu değişken öntanımlı olarak sıfır değeri ile
yüklüdür.
x = "aB"
if (x ~ /ab/) ... # bu test yanlış sonucu üretecektir.
IGNORECASE = 1
if (x ~ /ab/) ... # şimdi başarılmıştır.
Fakat IGNORECASE değişkenine değer atama metodu programın
taşınabilirliği açısından ve belirli kalıp kurallarına uyumlu
herhangi bir işlem yapılmıyor olunduğundan kullanılması pek tavsiye
edilmez. Onun yerine tolower() ve toupper() fonksiyonlarını
kullanmak daha sağlıklıdır.
gawk 3.0 sürümünden önce IGNORECASE değişkeninin değeri
yalnızca regexp ifadelerini etkilerdi. Katarları "==" ve "!=" ile
karşılaştırmalarında etkisi olmazdı. 3.0 sürümüyle birlikte hem
regexp ifadelerinde hemde katar karşılaştırmalarında etkili olmaya
başladı.
gawk 3.0 sürümüyle birlikte, küçük-harf ve büyük-harflerin
arasındaki karakterler ISO-8859-1 (ISO Latin-1) karakter seti
temeline dayanmaktadır. Bu karakter seti, geleneksel 128 ASCII
karakterleri süpersetidir. Bu set Avrupa dilleri ile kullanım için
uygun karakterleri bile sağlar.
IGNORECASE değişkeni, eğer gawk compatibility modda
çalışıyorsa etkisizdir. Büyük-küçük harf ayrımı compatibility
(uygun) modda her zaman anlamlıdır.
|
6.vi Ne Kadar Yazı Eşleştirilebilir?
Aşağıdaki örneği uygulayarak ne yaptığı hakkında biraz
düşünün :
|
]# echo aaaabcd | awk '{ sub(/a+/, "<A>"); print }'
|
Bu örnek, girdi değerini değiştiren sub() fonksiyonunu
kullanır (katarları işlemek için kullanılan bu awk fonksiyonunu
ilerde ayrıntılarıyla göreceğiz). Burda, /a+/ regexp'i "bir veya
daha çok 'a' karakterini" arar ve "<A>" değeriyle
değiştirir.
Girdi 'a' krakterlerini kapsar. Çıktı ne olur? Girdi içinde
"bir veya daha fazla" yani, awk bir, iki, üç, veya dört tane 'a'
karakteri eşleştirdi?
awk (ve POSIX awk) regexp'leri genellikle soldan itibaren
eşeleştirmeye başladığından, bu girdide uzun bir ardıllıkla 'a'
karakteri ile eşleştirme yapılmıştır. Böylelikle, örnekte, ardışık
dört 'a' karakterinden oluşan katar "<A>" katarıyla
değiştirilmiştir.
|
]# echo aaaabcd | awk '{ sub(/a+/, "<A>"); print }'
<A>bcd
|
Bu temel eşleştirme/eşleştirmeme testleri pek önemli
değildir. Fakat, yazı eşleştirmesi ve sub(), gsub(), ve gensub()
fonksiyonlarıyla yerine-koyma, alan ve kayıtlarda regexp-tabanlı
bölme işlemleri ile yapılıyorsa o zaman çok önemlidir.
|
6.vii Dinamik Regexplerin Kullanımı
'~' veya '!~' operatörünün sağ tarafına gelecek ifadenin,
regexp sabiti olması şart değildir (mesela bölü karakterleri
arasındaki karakter katarı). Bu herhangi bir ifade olmalıdır.
İfadeyi (katarı) bir değişkene atayarak gerekli işlemleri
yapabiliriz. Katarın içeriği regexp gibi kullanılabilir. Regexp bu
yolla, işlenmek için dinamik olarak çağrılabilir. Örneğin :
BEGIN { regexp_tanimlayici = "[A-Za-z_][A-Za-z_0-9]+" }
$0 ~ regexp_tanimlayici { print }
Burda regexp_tanimlayici adıyla tanımladığımız awk
değişkenine atadığımız regexp ifadesini, girdi kayıtlarıyla
karşılaştırarak uyumlu kayıtları ekrana bastırdık.
Not : '~' ve '!~' operatörlerini kullanıyorken, regexp
sabitlerini bölü karakterleri arasında yazmaktan farklı bir şekilde
çift tırnak arasında katar sabitleri şeklinde yazarız. Eğer katar
sabitlerini kullanıyorsanız, bu iki ana özelliğin özünü anlamış
olmalısınız; ilk anda awk programı okur ve ikinci anda da
operatörün sol tarafındaki değerle sağ tarafındaki kalıp üzerinde
katar eşleştirmesi yapar. Bu ifade katar değerli ifadedir fakat bir
katar sabiti değildir (yukarıdaki regexp_tanimlayici değişkeni
gibi).
Katar taraması yapılırken farklı olan nedir? Cevap, kaçırma
karakterleri ile, özellikle tersbölü ile birlikte belirlenen
katarlarda farklılıklar vardır. Çünkü bu katar sabitleri olarak
tanımlı regexp'ler içinde tersbölü karakterini kullanıyorken iki
terbölü karakteri yazmamız gereklidir.
Örneğin; /\*/ ifadesi '*' karakteri için regexp sabitidir.
Yalnız tek tersbölü'ye ihtiyaç vardır. Katar sabitinin de regexp
sabiti ile aynı işlemi yapmasını istiyorsak "\\*" şeklinde bir
kullanım uygulamalıyız. Birinci tersbölü karakteri ikinci tersbölü
karakterini kaçırmak için kullanılmıştır. Bu kaçırılan ve
böylelikle sadece tersbölü karakteri anlamına gelecek olan karakter
de '*' karakterini kaçırmak için kullanılmıştır. Yani bu katarla
aslında hm '\' hem de '*' karakterleri kaçırılmıştır.
regexp ve katar sabitlerinin her ikisi de regexp ifadesi
olarak tanımlanabilir, fakat hangisini kullanmak daha gereklidir?
Cevap, aşağıdaki birkaç sebepten dolayı "regexp sabitleri"'dir.
- Katar sabitlerinin yazımı çok karmaşık ve okuması da oldukça
zordur. regexp sabitlerinin programınızda kullanımıyla hata yapma
oranı daha da azalır. İki tür sabit arasındaki farkı programın
kodundaki hatalardan anlayamazsınız.
- regexp sabitleri çok daha etkili ve beceriklidir. awk, sizin
sağladığınız regexpi not eder, form dahilinde depolar ve çok etkili
kalıp eşleştirmesi. Katar sabiti kullandığınızda, awk, ilk olarak
form dahilinde katarı çevirir ve daha sonra da kalıp eşleştirmesi
yapar.
- regexp sabitlerini kullanmak daha iyi bir stildir. Çünkü regexp
sabitleri, tasarladığınız regexp eşleştirmesini çok açık bir
şekilde gösterir.
BÖLÜM I'e git - Bu
Bölümün Başına Git (BÖLÜM II) - BÖLÜM
III'e git -
Yasal Açıklamalar:
|
Bu belgeyi, Free Software Foundation tarafından yayınlanmış bulunan GNU Özgür Belgeleme Lisansının 1.1 ya da
daha sonraki sürümünün koşullarına bağlı kalarak kopyalayabilir, dağıtabilir ve/veya değiştirebilirsiniz.
Bu Lisansın bir kopyasını http://www.gnu.org/copyleft/fdl.html adresinde bulabilirsiniz.
Linux, Linus Torvalds adına kayıtlı bir ticarî isimdir.
Feragatname:
Bu belgedeki bilgilerin kullanımından doğacak sorumluluklar, ve olası zararlardan belge yazarları
sorumlu tutulamaz. Bu belgedeki bilgileri uygulama sorumluluğu uygulayana aittir.
Tüm telif hakları aksi özellikle belirtilmediği sürece sahiplerine aittir. Belge içinde geçen herhangi bir terim
bir ticarî isim ya da kuruma itibar kazandırma olarak algılanmamalıdır. Bir ürün ya da markanın kullanılmış olması
ona onay verildiği anlamında görülmemelidir.
|
İlgili Benzer Yazılar:
Arama önerileri:
linux,
programlama,
awk,
gawk,
shell programlama,
bash,
csh,
sh,
unix,
Kaynak gösterecekler için referans:
"Awk Programlama II",
Okan Özeren
A. Murat Eren,
http://www.KlavyeMonitor.com/awk2.html
|
|