(g) awk

Ajattelin aloittaa uuden keskustelun, vaikka se liittyykin muutamaan edelliseen viestiin liittyen awk:hon. Ohjelman opettelu on vaikeaa kun suomenkielinen opas on hyvin suppea ja englanninkielinen vaikea.

Alla on toimiva komento, mutta sen soveltamisessa muualle en ole onnistunut. Olisi mukava tietää, mitä seuraava osa oikein toimii ja mitkä ovat awk-komentoja:

/([0-9.]+).*</desc>/

Entä voisiko vastaavan tuloksen, siis numeron " 9.5 " , poimia esim. sillä tiedolla, että se on seuraavien tietojen välissä:

  1. Riihikallio (Tuusula)
  2. Km

tai että kohdan 1) tekstin jälkeen poimitaan kolme merkkiä ( “9” “.” “5” ) ?

Html-tekstissä on usein seuraavanlaisia merkkejä : , joten miten tuo alla oleva komento voi osata poimia juuri tuon kohdan, jossa haluttua 9.5 on. Luulisi, että tekstistä pitäisi löytää jotakin erityistä (esim. Riihikallio) ennenkuin haluttu kohta löytyy.

echo ‘Finish : 02/01/2008 13:17:58 : Riihikallio (Tuusula)9.5 Km13 Km/h2008-01-02T10:17:58Z53’ |

awk ‘{ if (match($0, /([0-9.]+).*</desc>/, m)) print m[1] }’

Awk:han on pieni ohjelmointikieli. Aaltosulkujen sisällä oleva lauseke on itse “ohjelma”.

Esimerkkinäsi käyttämä Awk -ohjelma käyttää säännöllisiä lausekkeita, joita mm. grep tukee myös. Kyseisen ohjelman ymmärtämisen kannalta olisi hyvä tuntea perusteet säännöllisistä lausekkeista (pääpaino tuossa on enemmän säännöllisten lausekkeiden puolella kuin itse Awk:ssa).

Esitetään esimerkissä mainittu ohjelma luettavassa muodossa:

awk '{  # ohjelma alkaa

if (match($0, /<desc>([0-9\.]+).*<\/desc>/, m))  # Tässä kutsutaan match -funktiota ja annetaan 
                                                 # sille parametreiksi; koko syötedata ($0), säännöllinen lauseke ja tulostaulukko (m).
                                                 # IF -lauseella tutkitaan mitä match -funktio palauttaa ja 
                                                 # jatketaan ohjelman suoritusta sen mukaan.
    # Jos match -funktio palauttaa TOSI -arvon (= osuma löytyi), tulostetaan osuman ensimmäinen ryhmä (toinen alkio taulukosta).
    print m[1]

}  # ohjelma päättyy'

[quote=“togo, post:1, topic:770”]tai että kohdan 1) tekstin jälkeen poimitaan kolme merkkiä ( “9” “.” “5” ) ?[/quote]Tuo vaatii hieman monimutkaisemman Awk -lausekkeen.

echo "Riihikallio (Tuusula)</name><desc>9.5 Km</desc><cmt>" | gawk '{ \ if (match($0, /<desc>([0-9\.]+).*<\/desc>/, m)) { \ split(m[1], s, //); # pilkotaan teksti ja tallennetaan se taulukkoon $s \ for(i=1; i <= NF; i++) { # pyöritetään silmukkaa niin kauan kunnes \ # muuttuja $i on sama kuin $NF (Number of Fields, \ # Awk:n globaali syöttömuuttuja) \ print s[i] # tulostetaan taulukosta $s muuttujan $i mukainen alkio \ } \ } \ }'
[size=8pt]Kenoviiva rivien lopussa on shellin “escapetus”-merkki, jolloin komento säilyy luettavassa muodossa ja sen voi silti kopioida suoraan komentoriville.[/size]

Awk taipuu paljon muuhunkin kuin pelkkien säännöllisten lausekkeiden käsittelyyn. Vahvimmillaan se on tekstin nopeassa ja vaivattomassa parsimisessa.

Jep,

Se “säännöllinen lauseke” on tosiaankin oleellinen osa ohjelmaa. Huomasin että sitä tarvitaan myös mm. grep -ohjelman kanssa. En tiedä, onko se paras/tehokkain/tms. tapa mutta etsin ensin grep-ohjelmalla oikean rivin ja sitten awk:lla oikeat merkit. Tällöin ainakin onnistun ja ymmärrän suunnilleen mitä olen tekemässä :slight_smile:

Kiitos taas paljon