Sie sind auf Seite 1von 12

Parsing Dostu: AWK!

zkan KIRIK
ozkan ~ enderunix.org

Parsing Dostu: AWK!


zkan KIRIK
Telif Hakk 2005 Permission is granted to copy, distribute and/or modify this document under the terms of the
GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with
no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

Iindekiler
1. Awkya bir baks .......................................................................................................................................................1
2. Awkda Kod Bloklar ................................................................................................................................................2
3. rneklerle Tekrarl Blok..........................................................................................................................................4
4. Regular Expressions ve Awk ....................................................................................................................................5
5. Diziler ve Awk............................................................................................................................................................8

iii

Blm 1. Awkya bir baks


Awk, genelde giris metnini inceleyip, metin ierisinde istediginin verilerin, belirlediginiz biimde dzenler ve
STDOUTa basar.
Awk, giris metnini bir veri tablosu gibi kabul eder. Tablonun her satr (Row) bir kayt gibi yorumlanr. Her stunu
ise Veri Alan (Field) olarak kabul yorumlanr. Stunlar ayrmak iin Alan Ayrac (Field Seperator) kullanlyor.
Aksi belirtilmedigi halde Field Seperator (FS) bosluk karakteridir.
Bir ls -l kts alp inceleyelim,
# ls -l

total 6
-rw-r--r--rw-------rw-r--r--

1 ryland
1 ryland
1 ryland

wheel
wheel
wheel

767 Jun 6 00:04 .cshrc


276 Nov 23 10:16 .history
248 Jun 6 00:04 .login

Bu sonucu, awkya girdi olarak verirsek, 4 Kayttan (Row) olusan bir veriyi inceliyor olacagz. Awk ile giris metni
incelenirken, her satr iin Alan Says (Number Of Fields) tekrar hesaplanr. Bu durumda ilk kaytta NR (Number Of
Row) degiskeni 1i gsterirken, NF (Number Of Fields) degiskeni ise 2yi gsterecektir. Ikinci kayt iin, NR = 2, NF
= 9 olacaktr
Awk, Alan ayracnn tekrarlanmas durumunda tek bir alan ayrac varms gibi davranr. rnegin:
"a b" ile "a

b" girdileri awk iin ayndr.

Awk, alanlar 1den baslayarak numaralandrr. Alanlara erismek isin alan numarasnn nne $ isareti eklenir.
rnegin birinci alana erismek iin, $1 ifadesi kullanlyor. Btn satr temsilen $0 ifadesi kullanlabilir. Yukardaki
ls -lde ilk iki satr incelersek;

NR = 1, NF = 2, $1="total", $2="6"
NR = 2, NF = 9, $1="-rw-r--r--", $2="1", $3="ryland", $4="wheel", $5="767", $6="Jun", $7="6", $8="00:

Blm 2. Awkda Kod Bloklar


Simdi

de, awknn, kodlarn nasl yorumladgndan bahsedelim,


Awk, kodlarn 3 asamada inceler:
1. Giris Metni Incelenmeden nce alsacak kod (BEGIN)
2. Metnin Her Satr iin tekrar edilecek kod
3. Inceleme tamamlandktan sonra alsacak kod (END)
rnek bir awk scripti ele alalm:
-- ornek.awk -# Giri
s incelenmeden nce al
sacak blm
BEGIN{
print "rnek AWK Programna Ho
sgeldiniz."
print "A
sa
gda, giri
s metninin sadece birinci sutnlar grntlenecektir."
}
# Metnin Her Satr iin tekrar edilecek kod
{
print $1
}
#
Inceleme tamamlandktan sonra al
sacak kod
END{
print "
Inceleme tamamland."
}
---------------

Scripti alstrrsak;
# ls -l | awk -f ../ornek.awk
rnek AWK Programna Ho
sgeldiniz.
A
sa
gda, giri
s metninin sadece birinci stunlar grntlenecektir.
total
-rw-r--r--rw-------rw-r--r--rw-r--r-
Inceleme tamamland.
#

Ayn isi awk ile commandline olarak yapmak istersek, scripti tek trnak trnak iine alarak yazn. Mesela;
# ls -l | awk {print $1}

Baska bir rnek ele alalm. ls -l nin ktsnda 5. stun dosya boyutlarn gsteriyor. Bu degerleri toplayp, toplam
dosya saysn ve boyutunu yazdiralim.
-- ornek2.awk -BEGIN {

Blm 2. Awkda Kod Bloklar


toplamboyut=0
}
{
if (NR != 1) {
toplamboyut=toplamboyut+$5
}
}

END {
dosyasayisi=NR-1 # 1 kartmamzn nedeni, ls -l de ilk satrn (total ile ba
slayan satr) dosya ol
print "Toplam,"
print dosyasayisi" dosya, "toplamboyut" byte."
}
----------------

Scripti alstralm,
# ll | awk -f ../ornek2.awk
Toplam,
4 dosya, 2018 byte.
#

Blm 3. rneklerle Tekrarl Blok


Bu sefer biraz daha farkl bir rnek ele alalm. Giris metninde kayt, tek bir satrda degil de, 2 ya da daha fazla satra
yaylmssa bu kaytlarn incelenmesi olayn inceleyelim;
-- giris.txt -Arayan numara 02121112233
5 cevapsiz cagri
Arayan numara 02164445566
3 cevapsiz cagri
Arayan numara 02127778899
19 cevapsiz cagri
---------------

Yukardaki sekilde bir girisimiz olsun. Bizden istenen kt ise, "02121112233 numarasndan 5 a
gr
var" seklinde her arama tek satra gelecek sekilde bir kt.
-- ornek3.awk -{
if ( (NR%2)==1 ) {
telno=$3
} else {
aramasayisi=$1
print telno" numarasndan "aramasayisi" a
gr var."
}
}
----------------

% operatr, soldaki saynn, sagdaki sayya blmnden kalan sayy veriyor (modulus). Bir saynn ikiye
blmnden kalan o saynn tek mi ift mi olduguna dair fikir edinmemizi saglyor. Bu durumda tek satrlarda
telefon numaras var, ift satrlarda ise cevapsz arama says yer alyor. Tek satrlarda telefon numarasn bir
degiskene atyoruz, ift satrlarda ise arama saysn grenip, sonucu ekrana yazdryoruz.
Simdi

scripti alstralm,
# cat giris.txt | awk -f
02121112233 numarasndan
02164445566 numarasndan
02127778899 numarasndan
#

ornek3.awk
5 a
gr var.
3 a
gr var.
19 a
gr var.

Blm 4. Regular Expressions ve Awk


Regexler awkda yazlrken / / arasna alnarak yazlr. (rnek: /^[0-9]/ gibi).
Awkda, bir ifadenin verilen regexle eslesip eslemedigini kontrol etmek iin, ~ (tilda) operatrn kullanyoruz.
Mesela giris metninde, rakam ile baslayan satrlar gsteren, digerlerini gstermeyen bir awk kodu yazalm:
-- giris.txt -EnderUNIX Yazlm Geli
stirme Takm
3numaral sayfa
1209348 nolu evrak
Bu satir yazilmayacak degil mi
---------------- ornek4.awk -{
if ( $1 ~ /^[0-9]/ ) {
print
}
}
----------------

Scripti alstrdgmzda;
# cat giris.txt | awk -f ornek4.awk
3numaral sayfa
1209348 nolu evrak
#

Kodlar incelersek, if satrnda, ($1 ~ /^[0-9]/) kosulu, 1.ci alanda ($1) ^[0-9] regexinin uyup
uymadgn kontrol ediyor.
Regexin kullanldg bir baska nokta ise, degistirme islemi (string substitution). Awk, degistirme islemi iin 2
fonksiyona sahip; sub ve gsub fonksiyonlar.
"sub" fonksiyonu verilen ifade ierisinde, aranan regexi ilk buldugunda degistirme islemini yapar ve aramay
durdurur. Ayn ifade ierisinde daha sonra ayn regexe uyan baska bir kelime varsa onlar degistirilmez. "gsub"
fonksiyonu ise verilen ifade ierisinde eslesen btn regexleri degistirir. Her iki fonksiyonda da eslesen kelime &
isareti ile temsil edilir.
rnegin, ls -l nin ktsnda bir takm degistirme islemlerini yapalm:
# ls -l
total 6
-rw-r--r--rw-------rw-r--r-#

1 ryland
1 ryland
1 ryland

wheel
wheel
wheel

767 Jun 6 00:04 .cshrc


276 Nov 23 10:16 .history
248 Jun 6 00:04 .login

-- ornek5.awk -{
sub(/-r/,"R",$0);
print

Blm 4. Regular Expressions ve Awk


}
----------------

Scripti alstrrsak,
# ls -l | awk -f ../ornek5.awk
total 6
Rw-r--r-- 1 root wheel 767 Nov
Rw------- 1 root wheel 276 Nov
Rw-r--r-- 1 root wheel 975 Nov
Rw-r--r-- 1 root wheel
0 Nov
#

24
24
24
24

09:20
09:20
09:21
09:21

.cshrc
.history
.shrc
.vimrc

Yukarda bahsettigimiz gibi, sub fonksiyonu sadece ilk eslesen kelimeyi degistiriyor.
-- ornek6.awk -{
gsub(/-r/,"R",$0);
print
}
----------------

Yukardaki rnegi uyguladgmzda,


# ls -l | awk -f ../ornek.awk
total 6
RwR-R-- 1 root wheel 767 Nov 24 09:20 .cshrc
Rw------- 1 root wheel 276 Nov 24 09:20 .history
RwR-R-- 1 root wheel 975 Nov 24 09:21 .shrc
RwR-R-- 1 root wheel
0 Nov 24 09:21 .vimrc
#

grndg gibi eslesen tm kelimeler degistirilmis.


Bir de & isaretinin kullanm hakknda bir rnek verelim:
-- ornek7.awk -{
for (i=1; i<=NF; i++) {
sub(/[0-9]/,"#\&",$i)
}
print
}
----------------

rnek7yi alstralm;
# ls -l | awk
total #6
-rw-r--r-- #1
-rw------- #1
-rw-r--r-- #1
-rw-r--r-- #1
#

-f ../ornek7.awk
root
root
root
root

wheel
wheel
wheel
wheel

#767 Nov #24 #09:20 .cshrc


#276 Nov #24 #09:20 .history
#975 Nov #24 #09:21 .shrc
#0 Nov #24 #09:21 .vimrc

Blm 4. Regular Expressions ve Awk


Yaptgmz islem, i degiskenini 1den NF (Number of Fields) degerine kadar arttrarak degistirerek her alanda tek tek
sub fonksiyonu araclg ile rakamla baslayan ifadelerin nne # karakteri ekliyoruz. Burada \& isareti, eslesen
kelimeyi temsil ediyor.

Blm 5. Diziler ve Awk


Awkda dizi anahtarlar rakamlarn yan sra kelimeler de olabiliyor. (rnegin dizi["adi"]="zkan")
Dizi islemlerinin kullanldg, ifconfigin ktsn parse eden bir script zerinde alsalm:
-- ornek8.awk -{
# Birinci alann son karakteri ":" ise ve ikinci alann ba
slangc "flags" ise
if ( ($1 ~ /\:$/) && ($2 ~ /^flags/) ) {
# yukardaki ko
sul do
gruysa birinci alan arayz ismidir
arayuz=$1
# arayuz isminin sonundaki ":" karakterini kaldralm
sub(/\:/,"",arayuz)
}
# Btn alanlar srayla tara
for (x=1; x<=NF; x++) {
# E
ger alann de
geri "inet" ise
if ($x=="inet") {
# bir sonraki alanda ip adresi var. alan sayac olan xi 1 arrtr.
x++
# arayz - ip adresi iftini diziye at.
ipadresleri[arayuz]=$x
}
}
}
END {
for (arayuz in ipadresleri) {
print "Arayz: "arayuz"\t IP Adresi: "ipadresleri[arayuz]
}
}
----------------

Yukardaki scriptin kts:


# ifconfig | awk -f ../ornek.awk
Arayz: lo0
IP Adresi: 127.0.0.1
Arayz: bge0
IP Adresi: 172.16.0.2
Arayz: bge1
IP Adresi: 192.168.0.1
Arayz: gif0
IP Adresi: 1.2.3.4
#
# ifconfig
bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=1a<TXCSUM,VLAN_MTU,VLAN_HWTAGGING>
inet 172.16.0.2 netmask 0xffffff00 broadcast 172.16.0.255
ether 00:14:c2:60:83:9b
media: Ethernet autoselect (1000baseTX <full-duplex>)
status: active
bge1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=1a<TXCSUM,VLAN_MTU,VLAN_HWTAGGING>
inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
ether 00:14:c2:60:83:9a

Blm 5. Diziler ve Awk


media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet 127.0.0.1 netmask 0xff000000
gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
tunnel inet 1.2.3.4 --> 5.6.7.8