Kalıp Tarama Ve İşleme Dili awk İle Linux'ta gawk Programlama (Bölüm II)


Okan ÖZEREN <okan.ozeren at students dot comu dot edu dot tr>
A. Murat EREN <meren at comu dot edu dot tr>


29/08/2003 Adana, v.0.1b


   BAŞLIKLAR

  1. BÖLÜM I (GİRİŞ-BAŞLANGIÇ)
  2. DÜZENLİ İFADELER (REGULAR EXPRESSIONS)
    1. Düzenli İfadeler Nasıl Kullanılır
    2. Karakter Kaçırma
    3. Düzenli İfade Operatörleri
    4. gawk'ya Özel Regexp Operatörleri
    5. Eşleştirmede Büyük Harf-Küçük Harf Hassasiyeti
    6. Ne Kadar Yazı Eşleştirilebilir?
    7. Dinamik Regexplerin Kullanımı
  3. 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.

  1. 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.
  2. 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.
  3. 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.

   


Teknik Bilgiler
Bilgisayar, Linux, Internet, WWW

http://teknik.ekitap.gen.tr/