HomeMapIndexSearchNewsArchivesLinksAbout LF
[Top bar]
[Bottom bar]
[Photo of the Author] 
Javier Palacios Bermejo 

Yazar hakkında: 

Javier İspanya'daki bir üniversitenin Astronomi bölümünde Prof. Dr. olarak çalışmaktadır. Görevi bir iş istasyonu grubunu çalıştırmaktır. İş yerinde günlük işlerinin tamamı Unix makineler üzerinde yapılmaktadır. Evvelki bazı problemlerinden ve deneyimlerinden ötürü slackware Linux'u kullanmayı tercih etti. Linux, diğer markalı Unix sistemlerinden çok daha iyi hale geldi. 

İçerik

  1. Awk hakkında genel bilgi
  2. Bir problem (ve bir çözüm)
  3. İleri düzeyde AWK
  4. Karışık satırlar üzerinde çalışma
  5. Programlama dili olarak awk
  6. İçerdiği kütüphaneler
  7. Sonuçlar
  8. Daha fazla bilgi

Awk ile ilgili örnekler: Kısa bir tanıtım

[Ilustration] Çeviri : Okan Kurtkaya ve İlknur Çolak

Özet:
Bu makale AWK ile yapabileceğiniz hileler hakkında size bazı bilgiler vermektedir. Bu bir ders niteliğinde olmayacak ancak, size kullanabileceğiniz canlı örnekler verecektir.



Gerçekte, bu fikir LinuxFocus dergisindeki Guido Socher tarafından yazılmış bir çift yazıyı okuduktan sonra aklıma geldi. Bunlardan biri, komutları bulmak ve anlatmak ile ilgili, bu bana gösterdi ki komut satırını kullanan tek kişi değilim. Çoğunlukla küçük GUI'ler bazı şeylerin nasıl yapıldığını tam olarak söylemezler (bu yöntem nedeniyle Windows yıllar önce gitti). Diğer yazının konusu kurallı deyimlerdi. Her ne kadar bu yazıda kurallı deyimlere sadece çok az değinilmişse de awk'dan ve sed ve grep gibi diğer komutlardan da tam verim alabilmek için bunları bilmeniz gerekmektedir.

Anahtar soru awk'nın gerçekten kullanışlı bir komut olup olmadığıdır. Cevap kesinlikle evetdir! Normal bir kullanıcı için text dosyalarını çalıştırabilmek yararlı olabilir, yeniden format atmak, vb...Ancak bir sistem yöneticisi için AWK son derece önemli bir hizmettir. /var/yp/Makefile civarında dolanın ya da önceki yazılara bakın. AWK her yerde kullanılır. 

Awk hakkında genel bilgi

Benim AWK hakkındaki ilk yazım, bunu unutmama yetecek kadar eskidir. Küçük bir Cray'den gerçekten büyük bazı çıktılar alarak çalışmak isteyen bir meslektaşım var. awk için Cray'deki ayrıntılı bilgiler bölümü gerçekten küçük, ancak o, her ne kadar nasıl kullanacağını tam olarak anlamış olmasa da AWK'ın aradığı şeye çok benzediğini söyledi.
Uzun bir zaman sonra, yeniden beraberiz, başka bir yerde tesadüfi bir başlangıç, başka bir meslektaşım AWK'yı kullanarak ilk sütunu tablodan genişletmişti:

awk '  '{print $1}'   file
Kolay, öyle değil mi? Bu basit taslak C'de karmaşık bir programlamaya, ya da diğer derleyici veya arayüz programlarına gerek duymaz. Bir satır AWK bunu halleder.

Bir zamanlar bir derste sütunları genişleterek dosyaların adını değiştirme gibi bazı şeyleri yapabileceğimizi öğrenmiştik:
ls -1 pattern | awk '{print "mv "$1" "$1".new"}' | sh

... ve daha fazlası. Önceki örnekte sed veya grep'i bir arada kullanmak bize daha güçlü araç sağlamıştır.

  1. isim içinde yeniden adlandırma yapmak

  2. ls -1 *old* | awk '{print "mv "$1" "$1}' | sed s/old/new/2 | sh
    (bununla birlikte bazı durumlarda çalışmayabilir, file_old_and_old da olduğu gibi)
  3. sadece dosyaları silmek (rm'i yalnız kullanarak yapılabilir, ancak 'rm -r' gibi bir yeniden adlandırma için ne denilebilir)

  4. ls -l * | grep -v drwx | awk '{print "rm "$9}' | sh
    (yine garip isimlerde ya da çalışma izinlerinde çalışmayabilir). Bunu kendinize ait bir dizinden başka yerde çalıştırırken dikkatli olun. Dosyaları sileriz!
  5. sadece dizinleri silme

  6. ls -l | grep '^d' | awk '{print "rm -r "$9}' | sh
    (Bence bu her durumda çalışır, ve bunu ls -p | grep /$ | wk '{print "rm -r "$1}' yazarak düzeltebiliriz )
    Bunu kendi dizininizden başka yerde denerken dikkatli olun. Dosyaları sileriz!
Gördüğünüz gibi aynı hesaplamalar üst üste tekrarlandığında AWK gerçekten yardımcı oluyor... ve bunun haricinde çoğunlukla bir şeyi 20 kere yapmaktansa AWK ile program yazmak çok daha eğlenceli olmaktadır.

Her ne kadar awk-command ismini kullanacak olsak da, awk aslında bir çeşit komut ismi değildir. awk, C ile uyuşan bir çok sözdizisine sahip bir programlama dilidir. Bir arayüz dilidir ve awk arayüzü (interpreter) verilen bilgileri işler.

Buyruğun kendisi ile ilgili:

# gawk --help
Usage: gawk [POSIX or GNU style options] -f progfile [--] file ...
        gawk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:          GNU long options:
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
        -m[fr] val
        -W compat               --compat
        -W copyleft             --copyleft
        -W copyright            --copyright
        -W help                 --help
        -W lint                 --lint
        -W lint-old             --lint-old
        -W posix                --posix
        -W re-interval          --re-interval
        -W source=program-text  --source=program-text
        -W traditional          --traditional
        -W usage                --usage
        -W version              --version

Bugları  Cc: arnold@gnu.ai.mit.edu ile bug-gnu-utils@prep.ai.mit.edu adresine bildirin,
Buyruk satırında programları sadece (') kesme ile ayıracağımıza, bunları bir dosyaya yazabiliriz, ve onu -f seçeneği ile çağırabiliriz, ayrıca yazdığımız programa bazı çok iyi bilinen değişkenleri ekleyebilmek için buyruk satırında -v var=val buyruğunu kullanırız.

Awk, zor öğrenilen ve tabloları yönetmeye yapılandırılmış bir dildir. Yani, içerideki bir alanda gruplanabilen ve kaydedilebilen bazı bilgiler. Buradaki avantaj, kaydedilebilen bilgilerin (ve aynı zamanda alanın) oldukça esnek olmasıdır.

Awk oldukça güçlüdür. Bir satırlık kayıtla çalışması için tasarlanmıştır, fakat bu nokta biraz gevşek olabilir. Benzerliklerin bazılarını görebilmek için, bazı ders verici (ve gerçek) örneklere göz atacağız.
 

  • Tabloları yazmak oldukça kolay bir yol

  • Belki, bir yerden alınan ASCII tablolarını yazmak zorunda kalmışsınızdır. Örneğin, hostname, ethernet ve bir listedeki IP numaraları. Bu tablolar çok büyük olduğu zaman onları okumak çok güç hale gelebilir ve bunları LaTeX'de görüntülenmiş olarak listelemek isteyebilirsiniz ya da en azından daha iyi bir biçimde. Eğer tablo basitse (ve/veya awk kullanmayı iyi biliyorsak), çok zor değildir.
     
    BEGIN {
      printf "LaTeX preample"
      printf "\\begin{tabular}{|c|c|...|c|}"
      }
    { printf $1" & "
      printf $2" & "
      .
      .
      .
      printf $n" \\\\ "
      printf "\\hline"
      }
    END {
      print "\\end{document}"
      }
    Aslında, bu bir generic program değildir, fakat hemen başlıyoruz...
    (Çift backslash'lar (\) gereklidirler çünkü bunlar kabuk çıkış karakterleridir.)
     
  • Çıktı dosyalarını dilimlemek

  •  

    SIMBAD diğer şeyler arasında astronomiksel nesnelerin veritabanıdır, gökyüzü üzerinde bir başlangıç konumu belirler. Geçmişte bir keresinde bazı nesnelerin çevresinde haritalar çizebilmeye gerek duydum. Arayüz, sonuçları metin dosyalarında kaydetmeyi sağlar, ve bu konuda iki yaklaşımım vardı: her nesne için bir dosya yaratmak, ya da onu tam bir girdi listesiyle beslemek, ben awk'ı büyük çıktı kütüklerini parçalara ayırmak için kullanıyorum. Açıkça, bazı çıktı karakterlerinden avantaja gereksinimim vardı.

    1. Her istem aşağıdaki gibi bir biçim ile başlık üretir. 

    2. ====> name : nlines <==== 
      Birinci başlık bize yeni bir nesne başladığını bildirir ve dördüncü ise nesnenin ne kadar girişe sahip olduğunu gösterir (buna rağmen veri çok fazla gerekli değildir.) 
    3. '|' karakteri,  farklı sütünları işaretlemek için liste çıktılarında kullanılır. Bu, çıktıyı kontrol edecek fazladan iki düzgü satırına gerek duyar ve ben sadece ilgilendiğim alanları alırım.
    ( $1 == "====>" ) {
      NomObj = $2
      TotObj = $4
      if ( TotObj > 0 ) {
        FS = "|"
        for ( cont=0 ; cont<TotObj ; cont++ ) {
            getline
            print $2 $4 $5 $3  >> NomObj
            }
        FS = " "
        }
      }
    NOT: Aslında, nesne adı geri gönderilmedi, ve o biraz daha karmaşıktı, ancak bu ders niteliğindeki bir örnek olarak verilmiştir.
  • Posta döngüsüyle oynamak
  • BEGIN {
      BEGIN_MSG  = "From"
      BEGIN_BDY  = "Precedence:"
      MAIN_KEY   = "Subject:"
      VALIDATION = "[MONTH REPORT]"
     
      HEAD = "NO"; BODY = "NO"; PRINT="NO"
      OUT_FILE = "Month_Reports"
      }
     
      {
     
      if ( $1 == BEGIN_MSG ) {
        HEAD = "YES"; BODY = "NO"; PRINT="NO"
        }
     
      if ( $1 == MAIN_KEY ) {
        if ( $2 == VALIDATION ) {
          PRINT = "YES"
          $1 = ""; $2 = ""
          print "\n\n"$0"\n" > OUT_FILE
          }
        }
     
      if ( $1 == BEGIN_BDY ) {
        getline
        if ( $0 == "" ) {
          HEAD = "NO"; BODY = "YES"
        } else {
          HEAD = "NO"; BODY = "NO"; PRINT="NO"
          }
        }
     
      if ( BODY == "YES" && PRINT == "YES" ) {
        print $0 >> OUT_FILE
        }
    
      }
    Belki bir posta listesini yönetiyor olabiliriz ve  zaman zaman, bazı özel mesajlar (örneğin, aylık raporlar) özel bir biçimde ('[MONTH REPORT] month , dept' gibi konularla) listeye eklenebilir. Aniden, yılın sonunda bütün bu mesajları diğerlerinin yanına kaydederek bir araya getirmeyi tasarlarız. 
    Bu, posta döngüsünü soldaki programdaki awk ile birlikte çalıştırırsak olabilir. 

    Kişisel bir dosyada yazılan raporların her birini biraraya getirmek demek, fazlalık üç tane düzgü satırı demektir. 

    NOT: Bu örneğin tahmin ettiğim gibi posta döngüsünü yapılandırdığı kabul edildi. Aslında gerçek biçimi bilmiyorum, ama bu program benim tesisatımda çalışmaktadır (tabi yine bazı ilginç durumlarda çalışmayabilir).
     Bu gibi programların planlanması sadece 5 dakika alır ve  5 dakika da yazması tutar (veya, en eğlenceli yoluyla, hiç düşünmeden, sadece deneme ve hatalarla 20 dakikadan fazla sürer).

    awk'ı başka bir çok taslak için kullandım (basit bir veritabanından alınan bilgilerle bir ağ sayfasını otomatik olarak meydana getirme) ve awk programlaması hakkında bir çok şeyin yapılabileceğine emin olacak kadar çok şey biliyorum.
    Sadece hayal gücünüzü uçuşa bırakın.

    Bir problem

    (ve bir çözüm)

    Problemimiz awk'ın mükemmel tabular bilgisine gereksinim duymasıdır, hatasız, awk sabit genişlikteki sütunlarla çalışmaz. Eğer awk'ın girdisini kendimiz hazırlarsak bu sorun teşkil etmez: alanları ayırmak için ortak olmayan bir şey seçin, daha sonra onu FS ile yerleştireceğiz ve hallettik sayılır!!! Eğer çoktan bir girdimiz varsa bu biraz daha sorunlu olabilir, çünkü alanların ayırıcı karakteri (mesela FS'in bir boşluk alanı vardır, bu nedenle bazı birleşik kelimeler bir problem olabilir. Mesela bunun gibi bir tablo: ) sorun meydana getirebilir. 
    1234  HD 13324  22:40:54 ....
    1235  HD12223   22:43:12 ....
    Bunu awk ile ele almak zordur. Benzeri girdiler bazen yapılması gereken buyruklar içerebilir. Bunun yanında, herhangi bir veri girdisi homojen olmadığından bu biraz benzer yapıdadır. Eğer bu karakterlerden yalnızca bir sütunum varsa, problemi çözebiliriz (eğer bir jenerik bölümünde birden fazla sütunun nasıl yapılacağını bilen varsa, lütfen beni haberdar etsin!). 
    Bir keresinde, bu tablolardan yukarıda tanımlanana benzer yapıda bir tanesiyle karşılaştım. Her zaman olduğu gibi, eklenen boşluklar ile birlikte, bu sütundan sonraki bir sütunu kullanarak sınıflandırma yaptım. Gömülü alanlarda da aynı sorunu veren sort +/-n.m ile bir çok kez denedim.
    Birden aklıma geldi, benim ayırmak istediğim sütun sonuncusuydu ve awk geçerli kayıtta ne kadar alan ayrılacağını biliyor. Bu nedenle, sonuncuyu çalıştırabilmek için yeterlidir (bazen $9, ve bazen $11, ama her zaman NF). Günün sonunda, istenilen sonuç elde edilmiş olur: 
    {
      printf $NF
      $NF = ""
      printf " "$0"\n"
    }
    Bu bana girdiye eşit bir çıktı verir, ancak son sütunla ilk pozisyona çıkar. Açıkça, bu metod sondan başlayarak üçüncü alana alınır, veya her zaman aynı değere sahip olan bir kontrol alanından sonraki alana alınır. 
    Son sütun ilk pozisyonuna hareket ettikten sonra, veriyi herhangi bir problemle karşılaşmadan sort edebiliriz. 
    Sadece fikirlerinizi ve hayal gücünüzü kullanın.

    İleri düzeyde AWK

    Karışık satırlar üzerinde çalışma

    Şu ana kadar, neredeyse bütün örnekler bütün girdi dosyaları satırları üzerinde işlem yapmaktadır. Ama, el kitabı sayfasında da yer aldığı gibi, sadece birkaç girdi satırı üzerinde işlem yapabilmek mümkündür. Birtanesi, satırların karşılaşabileceği farklı durumlarda komutlar gurubuna öncülük etmelidir. Uydurma durumu oldukça esnek olabilir, basit kurallı bir ifadeden bazı alanların kapasitesini öğrenip, özel yerel operatörlerle durumlarını guruplandırarak, onları değiştirebilirsiniz.

    Programlama dili olarak awk

    Diğer proglamlama dillerinde olduğu gibi, awk bütün gerekli akıcı kontrol yapılarını yerine getirir, operatörleri olabildiğince iyi ayarlar ve sayılarla ve sözcük dizileriyle uğraşaran fonksiyonları önceden tasarlar. Söz dizisi C'ye benzer.

    Ve, function anahtar sözcüğü ile kullanıcının belirli fonksiyonları kullanabilmesi ve bir girdi dosya satırını çalıştırıyormuş gibi birleşik buyrukları yazabilmesi elbette mümkündür. Ölçülmüş ortak değerlerden farklı olarak, awk'ın dizilerin boyutlarını belirleyebilme gibi bir özelliği de vardır.

    İçerdiği kütüphaneler

    Diğer bütün proglamlama dillerinde olduğu gibi, oldukça yaygın fonksiyonlar vardır ve bir düzgü parçasını kesip yapıştırmak rahatsızlık vermeye başlar. Kütüphanelerin çıkmasının nedeni budur. awk'ın GNU versiyonu ile, awk programı içerisinde içermek mümkündür. Ancak bu olabilecek şeylere dışardan bir bakış ve bu makalenin konusu dışında bir şeydir.

    Sonuçlar

    Kesinlikle, awk benzer amaçlar için tasarlanmış diğer araçlar kadar güçlü olmayabilir. Ancak oldukça kısa zamanlarda gereksinimlerimize tam olarak cevap veren küçük programlar yazabilmesi gibi büyük bir avantaja sahiptir.

    AWK kurulma amaçları için oldukça uygundur: Veriyi satır satır okuyun ve satırlardaki söz dizilerine ve  kalıplara kadar devam edin.

    /etc/password gibi dosyalar yeniden biçimlendirme ve AWK ile çalıştırma için idealdir. AWK bu gibi görevler için paha biçilmezdir.

    Tabi AWK yalnız değildir. Perl güçlü bir rakiptir fakat yine de birkaç AWK hilesi öğrenmeye değer.

    Daha fazla bilgi için

    Oldukça temel ve iyi belgelendirilmemiş komutlar, ama çevrenize bakındığınızda bir şeyler bulabilirsiniz. Genellikle, bu komutu içeren unix hakkındaki bütün kitaplar, ama onlardan sadece bazıları kullanışlı bilgilerin detaylarını verir. Yapabileceğimiz en iyi şey, elimize geçirdiğimiz herhangi bir kitabın sayfalarını karıştırmak, çünkü işinize yarayacak bilgiyi nerede bulacağınızı asla bilemezsiniz.

    Bu sanal yörenin bakımı LinuxFocus yazım gurubu tarafından yapılmaktadır 
    © Javier Palacios Bermejo  
    LinuxFocus 1999
    Çeviri bilgileri: 
    es -> -- Javier Palacios Bermejo
    es -> en Javier Palacios Bermejo,Ruben Sotillo, Manuel Rodriguez
     
    1999-09-14, generated by lfparser version 0.6