Ero sivun ”Awk” versioiden välillä
Siirry navigaatioon
Siirry hakuun
p
[[]]
p ([[]]) |
|||
(14 välissä olevaa versiota 10 käyttäjän tekeminä ei näytetä) | |||
Rivi 1: | Rivi 1: | ||
'''awk'''- | {{DISPLAYTITLE:{{lcfirst:{{PAGENAME}}}}}} | ||
'''awk'''-työkalun avulla voi helposti muuntaa tekstitiedoston rakennetta. awk ja sen laajennettu versio gawk kuuluvat Unix/Linux-käyttäjän perustyökaluihin silloin, kun kyseessä on: | |||
* puhtaan tekstitiedoston muuntaminen riveittäin toiseen muotoon | |||
* rivien suodattaminen pois tekstistä tavalla, johon [[grep]] ei kykene | |||
* laskujen laskeminen riveillä olevilla numeroilla | |||
== Johdanto == | |||
awk on skriptikieli ja samanniminen tulkki tälle skriptikielelle. Se on tarkoitettu tiedon hakemiseen selkeän rakenteen omaavista tekstitiedostoista ja tämän tiedon esittämiseen siistissä muodossa. Sen kehittäminen aloitettiin jo 1977 AT&T:n tutkimuslaboratoriossa (''[[Bell Labs]]''). Samassa paikassa aloitettiin muutama vuosi aikaisemmin myös [[Unix]]in kehittäminen. | |||
awk:n tilalla on monesti käytetty [[Perl]]iä, joka on kehitetty mm. ratkaisemaan samankaltaisia ongelmia kuin awk. awk:n opettelu ei silti ole turhaa, sillä: | |||
*awk on yksinkertaisempi (tärkeää jos mietit, kumman opettelisit ensin) | |||
*awk:n syntaksi on säännöllisempi | |||
*awk löytyy lähestulkoon järjestelmästä kuin järjestelmästä, Perl-tulkki ei | |||
*[http://pubs.opengroup.org/onlinepubs/009695399/utilities/awk.html IEEE:n Unix-standardi] määrittelee awk:n melko kattavasti, kun taas Perlin parametrit ja syntaksi ovat eläneet päätoteutuksen mukana | |||
Tärkeää on siis ymmärtää, että awk ei ole ainoa työkalu tietyntyyppisten ongelmien ratkaisemiseen. Eikä se ole myöskään monipuolisin. Se saattaa kuitenkin monissa tilanteissa olla yksinkertaisempi käyttää kuin Perl-skriptit. | |||
== Syntaksi == | |||
awk:n syntaksi on lähellä [[C]]:n syntaksia. Seuraavat asiat on kuitenkin syytä huomioida: | |||
* muuttujilla ei ole tyyppiä ja muunnokset tehdään automaattisesti. | |||
* taulukkoindekseinä voi käyttää periaatteessa mitä tahansa, tästä on paljon hyötyä niissä tehtävissä, joihin awk on ensisijaisesti tarkoitettu | |||
* syöttödata pilkotaan automaattisesti $1..n numeroiduiksi kentiksi yleensä välilyönnin kohdalta. | |||
* virheilmoitusten tulkinta voi olla hankalaa | |||
Yksinkertaisimmillaan awk:ta voidaan käyttää riveillä muotoa | |||
lauseke {komento} | |||
missä ''lauseke'' voi olla säännöllinen lauseke tai etsittävä merkkijono. Esimerkiksi rivi | |||
/linux/ {print} | |||
tulostaisi kaikki rivit, joilla esiintyy sana "linux". | |||
== awk-ohjelman käyttö == | |||
awk:ta käytetään komentoriviltä antamalla sille syötteenä skripti ja tiedosto, jota tällä skriptillä käsitellään. Skripti voidaan antaa joko komentoriviparametrina tai pidempien skriptien kanssa antamalla parametrina tiedosto, josta skripti ladataan. Eli joko | |||
awk -f skripti.awk tiedosto.txt | |||
tai | |||
awk '/linux/ {print}' tiedosto.txt | |||
== Kenttien käsittely == | |||
awk:n vahvin puoli on sen kyky käsitellä tiedoston sisältöä kenttinä. Esimerkiksi voimme helposti tulostaa tekstitaulukosta jokaisen rivin kolmannet solut. | |||
Tutkitaan esimerkiksi tiedostoa [[Passwd-tiedosto|/etc/passwd]] josta löytyy tietokoneen käyttäjien käyttäjätunnukset. Tämä tiedosto on muotoa | |||
<pre> | |||
root:x:0:0:root:/root:/bin/bash | |||
daemon:x:1:1:daemon:/usr/sbin:/bin/sh | |||
bin:x:2:2:bin:/bin:/bin/sh | |||
</pre> | |||
Leikitään, että haluamme tulostaa tiedostosta käyttäjien nimet. Käyttäjätunnus on jokaisella rivillä ensimmäinen kenttä, jos kentät erotellaan :-merkillä. Tehdään tällainen awk-skripti. | |||
Määritellään ensin erotinmerkiksi kaksoispiste asettamalla se muuttujan FS komennolla | |||
FS = ":" | |||
Komentoriviltä käytettäessä tämä voitaisiin asettaa valitsimella -F: | |||
awk -F ":" .... | |||
Tämän jälkeen awk erottelee jokaiselta riviltä vuorotellen kaksoispisteen erottamat merkkijonot (kentät) muuttujiin $1, $2,... Esimerkiksi tässä tapauksessa ensimmäisellä rivillä $1 olisi "root" ja $2 olisi "x". Nyt voimme tulostaa jokaiselta riviltä ensimmäisen kentät komennolla <tt>print $1</tt>, eli lopullinen awk-skriptitiedosto olisi | |||
FS = ":" | |||
{ print $1 } | |||
Toisaalta tämä voitaisiin ajaa myös yhdellä komennolla: | |||
awk -F : '{print $1}' /etc/passwd | |||
== BEGIN- ja END-lohkot == | |||
awk käsittelee syötteensä [[grep]]in ja [[sed]]in tavoin rivi kerrallaan. BEGIN- ja END-lohkoissa suoritetaan asiat, jotka on kuitenkin tarkoitus tehdä suoritusaikana vain kerran ennen ja jälkeen varsinaisen syötteen käsittelyä. | |||
awk 'BEGIN {aluksi} lauseke1 {jokaiselle lauseke1:lle} \ | |||
lauseke2 ... END {lopuksi}' tiedosto | |||
== Ehtolauseet ja vertailut == | |||
== Printf == | |||
Printf on awk:n funktio, jolla on mahdollista tehdä tarkempia muotoiluja tulostukselle. Se toimii samaan tapaan kuin vastaava funktio [[C]]-kielessä ja sen syntaksi on | |||
printf "muotoilumerkkijono", muuttuja1, muuttuja2, ... | |||
Ensimmäisenä annettava merkkijono sisältää tavallista tulostuvaa tekstiä ja voi lisäksi sisältää erikoismerkkejä, joiden paikalle sijoitetaan annettavat muuttujat sopivasti muotoiltuna. Ensimmäinen erikoismerkki käsittelee ensimmäisen parametrina annetun muuttujan, toinen toisen jne. | |||
Erikoismerkit alkavat prosenttimerkillä jota seuraa kirjain ja mahdollisesti numeroita (jos halutaan tulostaa prosenttimerkki, on käytettävä merkintää %%). Erikoismerkkejä ovat | |||
{| border=1 | |||
|- | |||
|'''Merkki''' | |||
|'''Selitys''' | |||
|- | |||
|%c | |||
|Tulostaa ASCII-numeroa vastaavan merkin. Esimerkiksi <tt>printf "%c", 65</tt> tulostaisi "A" | |||
|- | |||
|%d | |||
|Tulostaa kokonaisluvun | |||
|- | |||
|%i | |||
|Tulostaa kokonaisluvun | |||
|- | |||
|%e | |||
|Tulostaa luvun halutussa eksponenttimuodossa. Esimerkiksi <tt>printf "%4.3e", 1950</tt> tulostaisi "1.950e+03" (4 merkitsevää numeroa ja eksponenttina 3) | |||
|- | |||
|%f | |||
|Tulostaa desimaaliluvun | |||
|- | |||
|%g | |||
|Tulostaa luvun joko desimaali- tai eksponenttimuodossa sen mukaan, kummassa tarvitaan vähemmän merkkejä | |||
|- | |||
|%o | |||
|Tulostaa etumerkittömän oktaaliluvun | |||
|- | |||
|%s | |||
|Tulostaa merkkijonon | |||
|- | |||
|%x | |||
|Tulostaa etumerkittömän heksaluvun | |||
|- | |||
|%X | |||
|Tulostaa etumerkittömän heksaluvun käyttäen desimaaliluvuille 10-15 isoja kirjaimia | |||
|- | |||
|} | |||
== Silmukat == | |||
== Muuttujat == | |||
Shell-muuttujia voi välittää awk:lle luettelemalla ne parametreissa. Luvun 12 tulostus: | |||
a=12 | |||
echo '\n' | awk -v a=$a 'END {print a}' | |||
{| border=1 | |||
|- | |||
|'''Muuttuja''' | |||
|'''Selitys''' | |||
|- | |||
|FNR | |||
|Rivinumero tiedostossa, BEGIN-lohkossa 0. | |||
|- | |||
|FS | |||
|Kentän erotin, vakiona <space>. | |||
|- | |||
|NF | |||
|Kenttien lukumäärä rivissä, BEGIN-lohkossa määrittelemätön. | |||
|- | |||
|NR | |||
|Rivinumero syötteessä kokonaisuutena, BEGIN-lohkossa 0. | |||
|- | |||
|OFMT | |||
|Formaatti numeroille printf-komennossa, oletuksena "%.6g". | |||
|- | |||
|OFS | |||
|print-komennon kenttäerotin, oletuksena <space>. | |||
|- | |||
|ORS | |||
|print-komennon rivierotin, oletuksena <newline>. | |||
|- | |||
|RLENGTH | |||
|match-funktion tuloksen pituus. | |||
|- | |||
|RS | |||
|Rivierotin, vakiona <newline>. | |||
|- | |||
|RSTART | |||
|match-funktion paluuarvo, eli merkkijonon ensimmäisen merkin sijainti rivillä. | |||
|- | |||
|} | |||
Muuttuja $0 viittaa kulloiseenkin riviin kokonaisuudessaan. | |||
{}-lohkojen sisällä voi määritellä muuttujia C-sukuisten kielten tavoin: | |||
awk 'BEGIN {a=2} {if (NR % a == 0) print $0; else print "---"}' | |||
== Funktiot == | |||
{| border=1 | |||
|- | |||
|'''Funktio''' | |||
|'''Kuvaus''' | |||
|- | |||
|sub(ere, repl[, in ]) | |||
|Korvaa rivin ensimmäisen eren replillä. | |||
|- | |||
|gsub(ere, repl[, in ]) | |||
|Korvaa rivin kaikki eret repleillä. | |||
|- | |||
|length[([s])] | |||
|Palauttaa parametrin tai koko rivin pituuden. | |||
|- | |||
|match(s, ere) | |||
|Palauttaa eren alun paikan s:ssä. | |||
|- | |||
|split(s, a[, fs ]) | |||
|Paloittelee s:n a:han. fs oletuksena FS. | |||
|- | |||
|substr(s, m[, n ]) | |||
| - | |||
|- | |||
|tolower(s) | |||
| - | |||
|- | |||
|toupper(s) | |||
| - | |||
|- | |||
|close(exp) | |||
| - | |||
|- | |||
|getline | |||
|Siirtyy seuraavalle riville. | |||
|- | |||
|system(exp) | |||
|Komento awk:n ulkopuolelle. | |||
|} | |||
== Taulukot == | |||
== Esimerkkejä == | |||
Tiedostoa data.txt, jonka sisältö on seuraava: | |||
1 2 3 | 1 2 3 | ||
4 5 6 | 4 5 6 | ||
7 8 9 | 7 8 9 | ||
käsitellään seuraavanlaisen awk-ohjelman avulla: | |||
# tämä on awk ohjelma apu.awk | # tämä on awk ohjelma apu.awk | ||
# tämä begin lohko ajetaan kerran | # tämä begin-lohko ajetaan aluksi kerran | ||
BEGIN { | BEGIN { | ||
printf("alkutemput\n---------\n"); | printf("alkutemput\n---------\n"); | ||
} | } | ||
# | # Tässä välissä on varsinainen awk-ohjelmien 'äly'. Näitä lohkoja | ||
# voi olla useita, ja niiden eteen voi laittaa ehdon jolla ko. rivi ajetaan | # voi olla useita, ja niiden eteen voi laittaa ehdon, jolla ko. rivi ajetaan. | ||
# | # Jos alla olevan lohkon alun muuttaisi $1 == 4 { niin lohko ajettaisiin | ||
# vain riville joka alkaa numerolla 4. Ilman ehtoa se ajetaan kaikille riveille | # vain riville joka alkaa numerolla 4. Ilman ehtoa se ajetaan kaikille riveille | ||
{ | { | ||
Rivi 30: | Rivi 222: | ||
} | } | ||
Kun tiedosto data.txt syötetään ylläkuvatulle awk-ohjelmalle komennolla | |||
awk -f apu.awk <data.txt> | |||
on tulos seuraava: | |||
alkutemput | alkutemput | ||
---------- | ---------- | ||
Rivi 40: | Rivi 235: | ||
Seuraavalla komennolla etsitään pieniä, alle 100 merkin tiedostoja /etc-hakemistosta: | |||
ls -l /etc |awk '$5 < 100 {printf "%6s %s\n",$5,$8}' | |||
Poimitaan ja siistitään nykyinen resoluutio xrandr-komennon tulosteesta: | |||
* | xrandr -q | awk 'NR==2 {sub(/\+.*\+.*/,"",$3; print $3}' | ||
* | |||
== Muuta == | |||
awk:n on sanottu joskus olevan "write only language", ja sitä se onkin jos yrittää saada todella monimutkaisesta awk-ohjelmasta selkoa. Omat ohjelmat kannattaa tehdä siten, että kirjoittaa ja testaa ohjelman rivi kerrallaan. awk on parhaimmillaan lyhyissä muutaman rivin ohjelmissa. | |||
awk-ohjelmissa ei ole yleensä mitään rajoitusta käsiteltävien tiedostojen koolle, koska niitä käsitellään vain riveinä ja syöttö/tulostus putkina/virtoina. Awk-ohjelmat pystyvät käsittelemään varsin helposti hyvinkin suuria syöttö/tulostustiedostoja (satoja megatavuja). | |||
==Aiheesta muualla== | |||
*[http://www.unix.se/Awk Awk-artikkeli] unix.se-wikissä (ruotsiksi), josta tämä artikkeli on osittain käännetty. [[Keskustelu:Awk|Lisätietoja]]. | |||
*[http://www.cs.uu.nl/~piet/docs/nawk/nawk_toc.html awk-opas] | |||
*[http://www.cs.utah.edu/dept/old/texinfo/gawk/gawk_toc.html Gawk-opas] | |||
*[http://www.pement.org/awk/awk1line.txt Havainnollistavia yksirivisiä] | |||
[[Luokka: | [[Luokka:Komentorivin perustyökalut]] | ||