awk:n käyttö Linuxissa. Esimerkkejä AWK-komennoista Linuxissa

Teksti on Unixin sydän. "Kaikki on tiedostoa" -filosofia läpäisee koko järjestelmän ja sitä varten kehitetyt työkalut. Siksi töitä
tekstin kanssa on yksi vaadituista taidoista Järjestelmänvalvoja tai aloitteleva Linux-käyttäjä.

AWK on yksi parhaista tehokkaita työkaluja tekstin käsittelyyn ja suodattamiseen, joka on myös sellaisten ihmisten saatavilla, joilla ei ole mitään tekemistä ohjelmoinnin kanssa.

awk:n käyttö Linuxissa

Yksinkertaisin ja useimmin käytetty tehtävä on kenttien hakeminen vakiotulosteesta. Et löydä parempaa työkalua tähän tehtävään kuin awk. Oletuksena awk erottaa kentät välilyönneillä. Jos haluat tulostaa ensimmäisen kentän, sinun tarvitsee vain antaa awk-parametri $1:

echo "yksi kaksi kolme neljä" | awk "(tulosta 1 dollari)"

Kyllä, kiharan hammasraudan käyttö on hieman epätavallista, mutta tämä on vasta ensimmäinen kerta. Oletko jo arvannut, kuinka tulostetaan toinen, kolmas, neljäs tai muut kentät? Oikeasti se on 2 dollaria, 3 dollaria ja 4 dollaria.

echo "yksi kaksi kolme neljä" | awk "(tulosta 3 dollaria)"

Joskus on tarpeen esittää tiedot tietyssä muodossa, esimerkiksi valita muutama sana. AWK käsittelee helposti useiden kenttien ryhmittelyä ja mahdollistaa jopa staattisen tiedon sisällyttämisen:

echo "yksi kaksi kolme neljä" | awk "(tulosta $3, $1)"
kolme yksi

echo "yksi kaksi kolme neljä" | awk "(tulosta "foo:",$3,"| bar:",$1)"
foo: kolme | baari: yksi

Jos kentät erotetaan muulla erottimella kuin välilyönnillä, määritä haluttu erotin lainausmerkeissä -F-parametrissa, esimerkiksi ":" :

echo "yksi mississippi:kaksi mississippiä:kolme mississippiä:neljä mississippiä" | awk -F":" "(tulosta 4 dollaria)"
neljä mississippiä

Mutta erottimen ei tarvitse olla lainausmerkeissä. Seuraava tulos samanlainen kuin edellinen:

echo "yksi mississippi:kaksi mississippiä:kolme mississippiä:neljä mississippiä" | awk -F: "(tulosta 4 dollaria)"
neljä mississippiä

Joskus sinun on käsiteltävä tietoja, joissa on tuntematon määrä kenttiä. Jos sinun on valittava viimeinen kenttä, voit käyttää $NF-muuttujaa. Näin voit näyttää viimeisen kentän:

echo "yksi kaksi kolme neljä" | awk "(tulosta $NF)"
neljä

Voit myös käyttää $NF-muuttujaa saadaksesi toiseksi viimeisen kentän:

echo "yksi kaksi kolme neljä" | awk "(tulosta $(NF-1))"
kolme

Tai kentät keskeltä:

echo "yksi kaksi kolme neljä" | awk "(tulosta $((NF/2)+1))"
kolme

echo "yksi kaksi kolme neljä viisi" | awk "(tulosta $((NF/2)+1))"
kolme

Kaikki tämä voidaan tehdä apuohjelmilla, kuten sed, cut ja grep, mutta se on paljon vaikeampaa.

Ja vielä yksi awk-ominaisuus, tuki merkkijonojen käsittelijöille:

echo -e "yksi 1\n kaksi 2" | awk "(tulosta $1)"
yksi
kaksi

echo -e "yksi 1\n kaksi 2" | awk "(tulosta 2 dollaria)"
1
2

echo -e "yksi 1\n kaksi 2" | awk "(summa+=$2) END (tulostussumma)"
3

Tämä tarkoittaa, että meidän on suoritettava seuraava koodilohko jokaiselle riville. Tätä voidaan käyttää esimerkiksi laskemaan verkkopalvelimen lokista pyyntöjä varten siirrettyjen tietojen määrä.

Kuvittele, että meillä on käyttöloki, joka näyttää tältä:

23. heinäkuuta 18:57:12 HTTPD: "GET/foo/bar HTTP/1.1" 200 344
23. heinäkuuta 18:57:13 HTTPD : "GET/HTTP/1.1" 200 9300
23. heinäkuuta 19:01:27 HTTPD : "GET / HTTP / 1.1" 200 9300
23. heinäkuuta 19:01:55 HTTPD : "GET / Foo / Baz HTTP / 1.1" 200 6401
23. heinäkuuta 19:02:31 HTTPD: "? GET / Foo / Baz sivu = 2 HTTP / 1.1" 200 6312

Tiedämme, että viimeinen kenttä on siirrettyjen tavujen määrä, jolloin voimme käyttää $NF-muuttujaa:

< requests.log awk "{print $NF}"
344
9300
9300

Ohjelman päätarkoitus awk- awk-ohjelmointikielen tulkinta, jonka avulla voit luoda nopeasti ohjelman analysointia ja muuntamista varten tekstitiedostoja. Tyypillinen awk-skripti näyttää tältä:

malli1 (toiminto1) malli2 (toiminto2) ...

Ohjelma lukee syöttötiedosto tai suoratoistaa ja jäsentää jokaisen rivin kaavaosumaa varten. Jos osuma löytyy, kohdassa kuvatut toimet aaltosulkeet. Jos kuvio puuttuu, toimintoa sovelletaan jokaiselle riville. Jos toimintoa ei tehdä, rivi tulostetaan kohtaan vakiolähtö. Toiminto voi koostua lausesarjasta, jotka on erotettu puolipisteillä.

Kunkin rivin kolmannen kentän (sarakkeen, sanan) tulostaminen:

Koodi:

ls -l | awk "(print($3))"

Tulostaa kunkin rivin kaksi määritettyä kenttää:

Koodi:

ls -l | awk "(print($9,$1))"

Tulostuskentät välilyönneillä:

Koodi:

ls -l | awk "(print($9", ",$1))"

Jos haluat määrittää muun kentän erottimen kuin välilyönnin, käytä -F-vaihtoehtoa. SISÄÄN tässä tapauksessa Kentän erotin on kaksoispiste:

Koodi:

Awk -F: "(print($2))" $filenameForProcessing

Voit käyttää tiedostoon tallennettua awk-komentosarjaa seuraavasti:

Koodi:

Awk -f $scriptFilename $tiedostonimiForProcessing

awk-skriptitiedosto voidaan tehdä suoritettavaksi ja siihen voidaan määrittää vastaava sha-bang. Tällainen komentosarja ottaa tiedoston käsittelyä varten parametrina:

Koodi:

#!/usr/bin/awk -f

awk-muuttujat luodaan, kun niitä käytetään ensimmäisen kerran, ja ne voivat sisältää kokonaislukuja, liukulukuja tai merkkijonoja kontekstin mukaan. Erikoismuuttuja RS tallentaa tietueerottimen arvon (oletuksena \n) ja muuttuja FS tallentaa kenttäerottimen arvon (oletus - välilyönti). Jos jokin näistä muuttujista sisältää useamman kuin yhden merkin, kyseinen arvo tulkitaan säännölliseksi lausekkeeksi. Awk-kieli sisältää useita sisäänrakennettuja merkkijonoja ja matemaattiset funktiot, ehdolliset lausunnot ja silmukkaoperaattorit, tukee taulukoita ja määrittelyä mukautettuja toimintoja. Löydät sen Internetistä kattavat oppaat awk-kielellä sekä awk-skriptien automaattiset kääntäjät ("kääntäjät") muille kielille (esimerkiksi C tai Perl).

Erikoiskuviot ovat BEGIN ja END. Niitä ei verrata tulovirran merkintöihin. BEGIN-kuviotoiminto suoritetaan kerran ennen tulodatan lukemista, ja END-kuviotoiminto suoritetaan kerran tulodatan lukemisen jälkeen.

Esimerkki vierekkäisten päällekkäisten rivien poistamisesta tiedostosta:

Koodi:

Tiedostonimi=testi.txt
res=`awk "ALUE (PREV="") (if ($0 != PREV) (tulosta $0; PREV=$0))" $tiedostonimi`
echo "$res" > $tiedostonimi

Ennen kuin aloitamme, asetamme PREV-muuttujan arvoon tyhjä rivi. Muualla awk-komentosarjassa ei ole mallia, joten se suoritetaan millä tahansa merkkijonolla. Jos nykyinen rivi ei ole PREV, se tulostetaan ja kirjoitetaan sitten PREV-muuttujaan. Siten jokaista riviä käsiteltäessä, jos se osoittautuu yhtä suureksi kuin edellinen, sitä ei tulosteta.

Esimerkki kentän yhdistämisestä:

Koodi:

Awk "(a = 3 dollaria 4 dollaria; tulosta a)" $tiedostonimi

Esimerkki kenttien arvojen summaamisesta:

Koodi:

Awk "(a = $3+$4; tulosta a)" $tiedostonimi

"Valitsijan" käsite olisi ymmärrettävä "mallin" käsitteen laajennuksena. Jos komentorakenteessa on määritetty malli, yleensä mikä tahansa valitsin voi ilmestyä.

Kolmannen kentän testaaminen säännöllisen lausekkeen kanssa ja koko rivin tulostaminen onnistuessaan:

Koodi:

Awk "$3~/(7)$/ (tulosta)" $tiedostonimi

Tarkistaa ensimmäisen kentän yhtäläisyyden määritetyn merkkijonon kanssa ja tulostaa toisen kentän, jos se onnistuu.

Artikkelissa, jonka aion jakaa hyödyllisiä esimerkkejä, jotka auttavat minua ratkaisemaan jokapäiväisiä ongelmia ja helpottavat komentorivin käyttöä. Niille, jotka eivät vielä tunne AWK:ta, suosittelen, että hallitset tämän skriptikielen, siinä ei ole mitään monimutkaista. Aion liittää jokaiseen esimerkkiin pieniä kommentteja, jotka valaisevat tiettyjen operaattoreiden käytön vivahteita.
.

Etsimme riviä parametrilla sidososoite asetustiedostossa.

root@debian:~# awk '/bind-address/' /etc/mysql/my.cnf
sidososoite = 127.0.0.1
sidososoite = 192.168.1.110

Selitykset: AWK:ssa on seuraava syntaksi ja asetukset.

awk[-f ohjelman_tiedosto | 'ohjelma'] [-Fdelimiter]
[-v muuttuja=arvo] [tiedosto...]

−F arvo — määrittää erottimen (asettaa sisäänrakennetun FS-muuttujan arvon);
−f tiedosto - ohjelman teksti luetaan tiedostosta komentorivin sijaan. Lukeminen useista tiedostoista on tuettu;
−v var=arvo - vaaditun arvon määrittäminen muuttujalle;
−− — merkitsee vaihtoehtoluettelon lopun.

Esimerkki nro 2

Yllä olevassa esimerkissä haku tehdään tiedostosta, mutta AWK voi hyväksyä myös toisen komennon tulosteen. Yritetään monimutkaista esimerkkiämme vastaavasti.

root@debian-wordpress:~# cat /etc/mysql/my.cnf | awk '/bind-osoite/'
sidososoite = 127.0.0.1
sidososoite = 192.168.1.110

Kuten näette, tulos pysyi täsmälleen samana, vaikka suunnittelusta tuli tietysti monimutkaisempi. On sanottava, että tässä esimerkissä ei ole täysin suositeltavaa käyttää toista vaihtoehtoa, koska se on monimutkaisempi. Yritetään harkita muita tilanteita, joissa tällaisen mallin käyttö olisi perusteltua.

Esimerkki nro 3

Lista symbolisia linkkejä ja polut lopullisiin tiedostoihin.

root@debian:~# ls -l /bin/ | awk '/lrwxrwxrwx/ ( tulosta $9, $10, $11)'
bzcmp -> bzdiff
bzegrep -> bzgrep
bzfgrep -> bzgrep
bzless -> bzmore
lessfile -> lesspipe
lsmod -> kmod
mt -> /etc/alternatives/mt
nc -> /etc/alternatives/nc
netcat -> /etc/alternatives/netcat
open -> openvt
pidof -> /sbin/killall5
rbash -> bash
rnano -> nano
sh -> viiva
sh.distrib -> viiva

Selitykset: awk-ohjelma on mallipari ( kuvio) ja toimet ( (toiminta)), sekä käyttäjän määrittämien funktioiden määritelmät. Malli ja toiminta ovat seuraava näkymä: kuvio (toiminta) Malli tai toiminto voidaan jättää pois. Ensimmäisessä tapauksessa toiminto suoritetaan jokaiselle riville, toisessa suoritetaan normaali tulos näytölle, joka vastaa komentoa(Tulosta). Nämä avainsanoja ei voi yhdistää muihin malleihin.

Syöttömerkkijono koostuu yleensä erotetuista kentistä välilyöntejä. (Tätä oletusasetusta voidaan muuttaa käyttämällä sisäänrakennettua muuttujaa FS tai vaihtoehtoja -F-erotin.) Kentät on merkitty $1, $2, …; $0 viittaa koko riviin.

Esimerkki nro 4

Katsotaanpa yllä olevien tietojen perusteella esimerkkiä oletuserottimen muuttamisesta - katso luettelo kaikista käyttäjistä ilman lisätietoja.

root@debian:~# awk -F ":" '( tulosta $1 )' /etc/passwd
juuri
demoni
roskakori
sys
synkronoida
pelejä
mies

(Komentolähtöä lyhennetty)

Selitykset: koska tiedostossa /etc/passwd tietueet tallennetaan muodossa " root:x:0:0:root:/root:/bin/bash", on varsin loogista valita kaksoispiste erottimeksi ja näyttää ensimmäinen kenttä ( $1 ) jokainen rivi ( $0 ).

Esimerkki nro 5

Kaikki samassa tiedostossa käyttäjien kanssa, voit laskea heidän lukumääränsä.

root@debian:~# awk 'END ( print NR )' /etc/passwd
25

Selitykset: Erikoismallit ALKAA Ja LOPPU voidaan käyttää ohjauksen saamiseen ennen ensimmäisen syöttörivin lukemista ja vastaavasti viimeisen syöttörivin lukemisen jälkeen.

Awk on pääasiassa suoratoistoeditori kuten sed. Voit liittää tekstiä tähän ohjelmaan ja se voi muokata sitä rivi riviltä. Ohjelma osaa lukea myös tiedostosta. Awk on myös ohjelmointikieli. Tämä tarkoittaa periaatteessa sitä, että awk voi tehdä kaiken, mitä sed voi tehdä, ja paljon muuta.

Toisin kuin sed, awk voi muistaa kontekstin, tehdä vertailuja ja monia muita asioita, joita muut ohjelmointikielet voivat tehdä. Se ei esimerkiksi rajoitu yhteen riviin. Asianmukaisella taidolla se voi YHDISTÄÄ useita linjoja.

Eniten yksinkertainen muoto awk näyttää tältä:

Awk "(jotain_toimintoa täällä)"

"Some_action_here" voi olla yksinkertaisesti lauseke tuloksen tulostamiseksi tai jotain paljon monimutkaisempaa. Syntaksi on samanlainen kuin "C"-ohjelmointikielessä. Yksinkertainen esimerkki:

Awk "(tulosta $1, $3)"

tarkoittaa ensimmäisen ja kolmannen sarakkeen tulostamista, missä sarakkeet tarkoittavat "välilyönnillä erotettuja asioita". Valkoinen väli = sarkain tai välilyönti.

Live esimerkki:

Kaiku "1 2 3 4" | awk "(tulosta $1, $3)" 1 3

Osa kaksi: Mitä AWK voi tehdä?

AWK:n päätarkoitus elämässä on manipuloida syöttöään rivi riviltä. awk ohjelma toimii yleensä tyylillä

Jos se, mitä haluat tehdä, ei sovi tähän malliin, awk ei välttämättä sovi ideaasi.

Tavallista awk-ohjelmoinnin syntaksia voidaan kuvata seuraavasti:

awk-näyte (komennot)

Se tarkoittaa sitä

"Katso jokaista syöttöriviä nähdäksesi, onko siellä KUVIO. Jos se on siellä, suorita mikä on välillä ()"

Voit ohittaa joko SAMPLE tai COMMAND

Jos et määritä mallia, komentoa käytetään KAIKILLE riville.

Jos komento jätetään pois, tämä vastaa määrittämistä (tulosta vain rivi):

(Tulosta)

Tarkkoja esimerkkejä:

Awk "/#/ (tulosta "Tällä rivillä on kommentti")" /etc/hosts

tulostaa "Tällä rivillä on kommentti" jokaiselle riville, jolla on vähintään yksi "#" missä tahansa rivissä /etc/hosts

Muokkaus selkeyden vuoksi

Awk "/#/ (tulosta $0 ":\tTällä rivillä on kommentti)" /etc/hosts

Elementti "//" kuviossa on yksi tapa määrittää vastaavuus. On myös muita tapoja määrittää, vastaako merkkijono. Esimerkiksi,

Awk "$1 == "#" (tulosta "rivi alkaa hashilla")" /etc/hosts

vastaa rivejä, joiden ensimmäinen sarake on yksittäinen "#". Merkkijono "==" tarkoittaa KOKO ensimmäisen sarakkeen TARKAA OSTOA.

Muokkaus selkeyden vuoksi:

Awk "$1 == "#" (tulosta $0 "\trivi alkaa hashilla)" /etc/hosts

Toisaalta, jos haluat osittaisen vastaavuuden tietylle sarakkeelle, käytä "~"-operaattoria

Awk "$1 ~ /#/ (tulosta "JOSIN sarakkeessa 1 on hash")" /etc/hosts

MUISTA, ETTÄ ENSIMMÄINEN SARAKE VOI OLLA VALKOINEN VÄLILYÖNTI.

Muokkaus selkeyden vuoksi:

Awk "$1 ~ /#/ (tulosta $0 "\tSarakkeessa 1 on hash SOMEWHERE)" /etc/hosts

"#comment" syöttäminen vastaa

"#comment" syöttäminen vastaa MYÖS

Jos haluat tietyn vastaavuuden sanalle "merkkijono, joka alkaa täsmälleen #:llä ja välilyönnillä", käytät sitä

Awk "/^#/ (tee jotain)"

Useita otteluita

Awk käsittelee KAIKKI osuvat NÄYTTEET nykyinen linja. Joten jos käytämme seuraavaa esimerkkiä,

Awk " /#/ (tulosta "Kommentti on olemassa") $1 == "#" (tulosta "Kommentti ensimmäisessä sarakkeessa") /^# / (tulosta "Kommentti heti alussa") " /etc/hosts

KOLME merkintää tulostetaan seuraavan kaltaiselle riville:

# Tämä on kommentti

KAKSI merkintää haulle

# Tämä on sisennetty kommentti

ja vain yksi varten

1.2.3.4 isäntänimi # viimeinen kommentti

Kontekstin seuranta

Kaikkia merkkijonoja ei luoda samanarvoisiksi, vaikka ne näyttäisivätkin samalta. Joskus haluat tehdä jotain merkkijonolle riippuen sitä edeltävistä riveistä.

Tässä nopea esimerkki joka tulostaa rivit "ADDR", jos et ole "salainen"-osiossa

Awk " /secretstart/ ( secret=1) /ADDR/ ( if(secret==0) tulosta $0 ) /* $0 on täysi rivi*/ /salainen/ (salaisuus=0) "

Seuraava tulostaa sisällön, jonka sisällä on "ADDR", ellei merkkijonoa "secretstart" ole nähty. TILAAMISASIOITA. Jos kirjoitat sen esimerkiksi näin:

Awk " /ADDR/ ( if(secret==0) print $0 ) /* $0 on koko rivi */ /secretstart/ ( secret=1) /secretend/ ( secret=0) "

ja anna seuraava syöte

ADDR normaali addr secretstart ADDR salainen addr ADDR toinen salainen addr kolmas salainen ADDR secretend ADDR normaali myös

sitten tulostetaan ensimmäinen "salainen" osoite. Koska alkuperäinen esimerkki piilottaa molemmat salaisuudet.

Osa 3: Erikoismuuttujat

Olemme jo puhuneet tavallisesta awk-syntaksista. Nyt aletaan katsoa muodikkaita asioita.

awk:lla on "erityisiä" vastaavia merkkijonoja: " ALKAA"ja" LOPPU"

Direktiivi ALKAA kutsutaan kerran ennen rivien lukemista tiedoista, ei koskaan enää.

Direktiivi LOPPU kutsutaan, kun kaikki rivit on luettu. Jos annetaan useita tiedostoja, se kutsutaan vasta, kun viimeisin tiedosto on valmis.

Yleensä käytät ALKAA eri alustuksiin ja LOPPU yhteenvedon tekemiseen tai siivoamiseen.

BEGIN ( maxerrors=3 ; logfile=/var/log/something ; tmpfile=/tmp/blah) ... ( blaa bla bla ) /^header/ ( headercount += 1 ) END ( printf("ylätunnisteiden kokonaismäärä=% d\n", otsikkomäärä);

Tämä esimerkki laskee, kuinka monta kertaa "otsikko" näkyy syöttötiedostossa ja tulostaa kokonaissumman vasta koko tiedoston käsittelyn jälkeen.

AWK:lla on myös monia muita erikoisarvoja, joita voit käyttää ( ) -osiossa. Esimerkiksi,

Tulosta NF

näyttää nykyisen rivin sarakkeiden kokonaismäärän (kenttien lukumäärä). TIEDOSTON NIMI on nykyinen tiedostonimi, mikä tarkoittaa, että tiedostonimi on välitetty awk:lle eikä putkelle.

ET VOI MUUTTAA NF omillaan.

Sama muuttujan kanssa NR, joka kertoo, kuinka monta riviä olet käsitellyt. ("Tietueiden määrä" - Tietueiden määrä)

On muitakin erikoismuuttujia, jopa sellaisia, joita VOI muuttaa kesken ohjelman.

Osa neljä: Yksinkertaisia ​​awk-esimerkkejä

Havainnollistaaksemme ja vahvistaaksemme sitä, mitä on sanottu, katsotaanpa muutamia konkreettisia esimerkkejä. Niitä varten tarvitsemme kolme pientä tekstitiedostoa.

Seuraavia esimerkkejä varten luodaan field_data.txt-tiedosto, jossa on seuraava sisältö:

Ruusut ovat punaisia, violetit sinisiä, sokeri on makeaa, ja niin olet sinäkin.

Echo -e "Ruusut ovat punaisia,\nvioletit ovat sinisiä,\nSokeri on makeaa,\nJa niin olet sinäkin." >field_data.txt

Luodaan seuraavan sisällön sisältävä letters.txt-tiedosto

A bb ccc dddd ggg hh i

SISÄÄN komentorivi se voidaan tehdä näin:

Echo -e "a\nbb\nccc\ndddd\nggg\nhh\ni" > letters.txt

Luodaan lopuksi seuraavan sisällön sisältävä sähköpostitiedosto:

Amelia 555-5553 [sähköposti suojattu] F Anthony 555-3412 [sähköposti suojattu] Becky 555-7685 [sähköposti suojattu] Lakiesitys 555-1675 [sähköposti suojattu] A Broderick 555-0542 [sähköposti suojattu] R Camilla 555-2912 [sähköposti suojattu] R Fabius 555-1234 [sähköposti suojattu] F Julie 555-6699 [sähköposti suojattu] F Martin 555-6480 [sähköposti suojattu] A Samuel 555-3430 [sähköposti suojattu] A Jean-Paul 555-2127 [sähköposti suojattu] R

Tämä voidaan tehdä komentorivillä seuraavasti:

Wget https://raw.githubusercontent.com/tdhopper/awk-lessons/master/data/mail-data -O mail-data

Yksinkertainen malli (näyte)

Jos tarvitsemme yli kaksi merkkiä pitkiä rivejä ja haluamme käyttää oletustoimintoa ( Tulosta), niin saamme:

Awk "pituus $0 > 2" kirjaimet.txt bb ccc dddd ggg hh

$0 on sisäänrakennettu muuttuja, joka sisältää merkkijonon.

Yksinkertainen toiminto

Jos emme määritä kuviota, jokainen rivi täsmää. Triviaali toimenpide olisi jokaisen rivin tulostaminen:

Awk "( tulosta )" letters.txt a bb ccc dddd ggg hh i

Toiminnon käyttäminen pituus toimintamme avulla voimme saada jokaisen rivin pituuden:

Awk "( tulostuspituus )" letters.txt 1 2 3 4 3 2 1

Tämä toiminto koskee ehdoitta koko riviä. Voimme myös määritellä tämän nimenomaisesti:

Awk "( tulostuspituus $ 0 )" letters.txt 1a 2bb 3cc 4dddd 3ggg 2hh 1i

Awk:ssa on erikoissäätimet joidenkin koodin suorittamiseen ennen tiedoston syöttämistä ja tiedoston valmistumisen jälkeen.

Awk "BEGIN ( print "HI" ) ( print $0 ) END ( print "BYE!" )" letters.txt HI a bb ccc dddd ggg hh i BYE!

Meillä voi olla lisää elementtejä ohjaus tulostuksen aikana printf.

Awk "BEGIN ( printf "%-10s %s\n", "Nimi", "Numero" \ printf "%-10s %s\n", "----", "------" ) \ ( printf "%-10s %s\n", $1, $2 )" mail-data Niminumero ---- ------ Amelia 555-5553 Anthony 555-3412 Becky 555-7685 Bill 555-1675 Broderick 555-0542 Camilla 555-2912 Fabius 555-1234 Julie 555-6699 Martin 555-6480 Samuel 555-3430 Jean-Paul 555-2127

Näytteiden ja toimintojen yhdistäminen

Tietenkin kuvioita ja toimintoja voidaan yhdistää niin, että funktiota käytetään vain, jos merkkijono vastaa kuviota.

Voimme tulostaa kaikkien yli 2 merkkiä pitkien rivien pituudet.

Awk "pituus($0) > 2 ( tulostuspituus($0) )" letters.txt 3 4 3

Itse asiassa meidän ei tarvitse rajoittaa Awkia vain yhteen malliin! Meillä voi olla mielivaltainen määrä kuvioita, jotka on rajattu puolipisteillä tai rivinvaihdoilla:

Awk "length($0) > 2 ( tulosta "Long:" pituus($0) ); pituus($0)< 2 { print "Short: " length($0) }" letters.txt Short: 1 Long: 3 Long: 4 Long: 3 Short: 1

Paljon kenttiä

Awk on suunniteltu yksinkertaiseen tietojenkäsittelyyn, jossa on useita kenttiä peräkkäin. Kentän erotin voidaan määrittää avaimella -F.

Esimerkki tiedostosta, jossa erotin on välilyönti:

Awk "( print )" field_data.txt Ruusut ovat punaisia, violetit sinisiä, sokeri on makeaa, ja niin olet sinäkin.

Jos määritämme kenttäerottimen, voimme tulostaa kunkin rivin toisen kentän:

Awk -F " " "( tulosta $2 )" field_data.txt are are on niin

Emme saa virheilmoitusta, jos rivillä ei ole vastaavaa kenttää; meille näytetään yksinkertaisesti tyhjä rivi:

Awk -F " " "( tulosta $4 )" field_data.txt sinulle.

Koska oletuserotin on välilyönti, edellinen komento olisi antanut täsmälleen saman tuloksen ilman vaihtoehtoa -F. Jos haluat merkityksellisemmän esimerkin, luodaan toinen tiedosto hinnat.txt seuraavalla sisällöllä:

Pilcrow, Humphrey, 3 Pilcrow, Zora, 1 Plinius, Oldone, 4 Razniecki, Anton, 7 Russell, Bertrand,0

Nyt osoitamme erottimena , (pilkku) ja näytä toisen sarakkeen sisältö:

Awk -F "," "( tulosta $2 )" rates.txt Humphrey Zora Oldone Anton Bertrand

Erotinlauseke tulkitaan säännölliseksi lausekkeeksi.

Awk -F "((niin)?ovat|on) " "(tulosta "Kenttä 1: " $1 "\nKenttä 2: " $2)" field_data.txt Kenttä 1: Ruusut Kenttä 2: punainen, Kenttä 1: Violetti Kenttä 2 : sininen, kenttä 1: sokeri Kenttä 2: makea, kenttä 1: ja kenttä 2: sinä.

Säännölliset lausekkeet

Kuviot voivat olla säännöllisiä lausekkeita, eivät vain sisäänrakennettuja toimintoja.

Voimme käyttää säännöllisiä lausekkeita löytääksemme kaikki Unix-maailman sanat, joissa on 5 vokaalia peräkkäin.

Awk "/(5)/" /usr/share/dict/words cadiueio Chaouia euouae Guauaenok

Muuttujien välittäminen ohjelmaan

Vaihtoehto -v Awk antaa meille mahdollisuuden siirtää muuttujia ohjelmaan. Voimme käyttää tätä esimerkiksi kovakoodivakioihin.

Awk -v pi=3.1415 "ALKU ( tulosta pi )" 3.1415

Voimme myös käyttää -v välittää Bash-muuttujat Awk-muuttujina

Awk -v user=$USER "BEGIN ( print user )" mial

Jos-else ilmaisuja

Tai muuten Awkin lausekkeet näyttävät tältä:

Jos (kunto) runko-niin

Esimerkiksi:

Tulostaf "1\n2\n3\n4" | awk \ "( \ if ($1 % 2 == 0) tulosta $1, "on parillinen"; \ muuten tulosta $1, "on pariton" \ )" 1 on pariton 2 on parillinen 3 on pariton 4 on parillinen

Pyörät

Awk sisältää useita silmukkalausekkeita: sillä aikaa, tehdä, kun Ja varten.

Niissä on odotettu C-syntaksi.

Awk\"BEGIN(\i=0;\while(i< 5) { print i; i+=1; } \ }" 0 1 2 3 4 awk \ "BEGIN { \ i = 0; \ do { print i; i+=1; } while(i < 0) \ }" 0 awk \ "BEGIN { \ i = 0; \ for(i = 0; i<5; i++) print i \ }" 0 1 2 3 4

varten voi myös määrittää silmukan taulukkonäppäinten kautta, mikä keskustellaan myöhemmin.

Osa viisi: Soittotoiminnot

AWK:n seuraava komponentti on kaikki sen erityiset sisäänrakennetut toiminnot.

AWK:ssa on ominaisuuksia, jotka tekevät keskimääräisen C-ohjelmoijan melko onnelliseksi. Tässä on sellaisia ​​asioita kuin sin()/cos()/tan(), rand(),index(), sprintf(), tolower(), system()

Toiminnot on ryhmitelty ja niitä voi tarkastella seuraavasti:

Matemaattinen

+, -, /, *, sin(), cos(), tan(), atan(), sqrt(), rand(), srand()

Ne puhuvat puolestaan, ainakin minä haluaisin niin ajatella.

Awk -v pi=3.1415 "BEGIN ( tulosta exp(1), log(exp(1)), sqrt(2), sin(pi), cos(pi), atan2(pi, 2) )" 2,71828 1 1,41421 9,26536 e-05-1 1,00387

Ohjelma voi generoida satunnaisluvun välillä (0, 1).

Oletuksena Awk alkaa samasta alusta (siemenestä) Awkille. Tämän komennon suorittaminen kahdesti peräkkäin palauttaa saman tuloksen:

Awk "BEGIN ( tulosta rand(); tulosta rand() )" 0,237788 0,291066

Voit asettaa alun (siemen) käyttämällä srand-toimintoa:

Awk "BEGIN ( srand(10); print rand(); print rand() )" 0.255219 0.898883 awk "BEGIN ( srand(10); print rand(); print rand() )" 0.255219 0.898883

Toiminto int palauttaa "x:tä lähimmän kokonaisluvun x:n ja nollan välillä, jolloin ensimmäinen nolla hylätään."

Awk "BEGIN ( print "int(0.9) = " int(0.9); print "int(-0.9) = " int(-0.9) )" int(0.9) = 0 int(-0.9) = 0

Merkkijonojen manipulointi

  • indeksi() kertoo, esiintyykö merkkijono alimerkkijonossa ja jos on, missä.
  • ottelu() samanlainen, mutta toimii säännöllisissä lausekkeissa.
  • sprintf() antaa sinulle tapoja muotoilla tulostetta ja tehdä muunnoksia matkan varrella. Tämän pitäisi olla tuttu kaikille, jotka ovat käyttäneet printf():tä C:n kanssa. Esimerkiksi
newsstring=sprintf("yksi on luku %d, kaksi on merkkijono %s\n", yksi, kaksi); tulostaa uutisjonoa

"%d" sanoo "tulosta minua vastaava arvo desimaalilukuna"
"%s" sanoo "tulosta minua vastaava arvo merkkijonona"

Nuo. jos haluat ketjuttaa kaksi riviä ilman taukoja, YKSI tapa olisi käyttää

Newstring=sprintf("%s%s", yksi, kaksi)

  • pituus() antaa sinulle vain helpon tavan laskea rivin merkkien määrä, jos tarvitset sitä.

Toiminto osastr(s, m, n) palauttaa alimerkkijonon n-hahmot paikasta alkaen m, laskettuna 1:stä.

Awk "( tulosta $1, substr($1, 2, 3) )" field_data.txt Roses ose Violets iol Sugar uga And nd

indeksi(t, t) palauttaa `aseman s jossa linja esiintyy t, tai 0, jos sitä ei tapahdu."

Indeksin malli ei ole säännöllinen lauseke.

Awk "( tulosta $1, index($1, "s") )" field_data.txt Ruusut 3 Violettia 7 Sokeri 0 ja 0

ottelu(t, r) palauttaa paikan sisään s jossa säännöllinen lauseke esiintyy r, tai 0, jos sitä ei tapahdu. Muuttujat RSTART Ja PITUUS on asetettu vastaavan merkkijonon sijaintiin ja pituuteen.

ottelu- Miten on, että indeksi paitsi että kuvio on säännöllinen lauseke.

Awk "( tulosta $1, vastaa($1, "") )" field_data.txt Ruusut 3 Violetit 7 Sokeri 1 Ja 0 # "Etsi kolme tai useampia toistuvia kirjaimia" awk "( match($1, "(3)"); tulosta $1, "\tpattern start:", RSTART, "\tpattern end:", RLENGTH )" letters.txt a kuvion alku: 0 kuvion loppu: -1 bb kuvion alku: 0 kuvion loppu: -1 ccc kuvion alku: 1 kuvio loppu: 3 dddd kuvion alku: 1 kuvion loppu: 3 ggg kuvion alku: 1 kuvion loppu: 3 hh kuvion alku: 0 kuvion loppu: -1 i kuvion alku: 0 kuvion loppu: -1

split(s, a, fs) jakaa merkkijonon elementtijoukoksi a, a, …, a ja palauttaa n.

Jako tapahtuu säännöllisellä lausekkeella fs tai kenttäerottimella FS, Jos fs ei annettu. Tyhjä merkkijono kentän erottimena jakaa merkkijonon elementtijoukoksi merkki merkiltä.

Awk "BEGIN ( print split("It-wis_the-best_of-times", output_array, "[-_]"), output_array, output_array )" 6 oli paras

ala(r, t, s) korvaa kanssa t säännöllisen lausekkeen ensimmäinen esiintyminen r linjassa s. Jos s:tä ei anneta, käytä $0

s on merkkijono, jossa korvaus tapahtuu. Sen sijaan, että palautettaisiin uusi merkkijono, jossa vaihto on tehty, palautetaan tehtyjen vaihtojen lukumäärä (0 tai 1).

Awk "BEGIN ( s = "Se oli parhaat ajat, se oli pahin kerta"; \ print "Osumusten määrä korvattu:", sub("times", "gifs", s); \ print s )" Num. korvatut ottelut: 1 Se oli paras gifistä, se oli pahin kerta

gsub tekee samaa kuin sub paitsi että kaikki säännöllisen lausekkeen esiintymät korvataan; sub Ja gsub palauttaa vaihtojen määrän.

Awk "BEGIN ( s = "Se oli parhaat ajat, se oli pahin aika"; \ print "Num. vastaavuuksia korvattu:", gsub("times", "cats", s); \ print s )" Num. korvatut osumat: 2 Se oli kissojen paras, se oli kissoista huonoin sprintf sprintf(fmt, expr, ...) palauttaa merkkijonon, joka on tuloksena muotoilusta expr ... printf(3) -muodon mukaan fmt awk "BEGIN ( x = sprintf("[%8.3f]", 3.141592654); tulosta x )" [ 3.142]

Järjestelmätason toiminnot

järjestelmä() voit kutsua mahdollisesti MITÄ tahansa suoritettavaa tiedostoa järjestelmässä. Kohdeohjelma voi olla sinun $PATH, tai voit määrittää sen käyttämällä absoluuttista polkua.

Esimerkiksi pelottava

System("rm -rf $HOME");

System("/bin/kill 1")

Jos haluat tehdä monimutkaisempia asioita, päädyt todennäköisesti tekemään jotain vastaavaa

Sysstring=sprintf("jokin komento %s %s", arg1, arg2); järjestelmä (järjestelmämerkkijono)

kiinni() on tärkeä ominaisuus, joka jää usein huomiotta. Tämä johtuu luultavasti siitä, että ei ole selvää kutsua avata(), jotta ihmiset eivät ajattele haastetta kiinni(). Ja useimpiin tarkoituksiin tämä ei ole välttämätöntä. Mutta sinun TÄYTYY TEHDÄ TÄMÄ, jos käsittelet useampaa kuin yhtä tulostustiedostoa.

Awk antaa sinulle mahdollisuuden avata mielivaltainen tiedosto lennossa. Esimerkiksi

/^file/ ( tulosta $3 >> $2)

pitäisi ottaa rivi "file output here-is-a-word", avata tiedosto "output" ja tulostaa "here-is-a-word" siihen.

AWK on "älykäs" siinä mielessä, että se seuraa mitä tiedostoja avaat ja PITÄÄ ne auki. Se olettaa, että jos avasit tiedoston kerran, teet sen todennäköisesti uudelleen. Valitettavasti tämä tarkoittaa, että jos avaat PALJON tiedostoja, tiedostokuvaajat saattavat loppua. Joten kun tiedät, että olet valmis käsittelemään tiedostoa, sulje se. Joten parantaaksesi yllä olevaa esimerkkiä, sinun pitäisi käyttää jotain seuraavista riveistä:

/^tiedosto/ ( if ($2 != vanha tiedosto) ( sulje(vanha tiedosto) ); tulosta $3 >> $2 ; vanha tiedosto = $2; )

Osa kuusi: Taulukot

Array käsite

Olemme jo tarkastelleet muuttujia niminä, jotka sisältävät arvon. Taulukot ovat muuttujien laajennus. Taulukot ovat muuttujia, jotka sisältävät useamman kuin yhden arvon. Ne voivat sisältää useamman kuin yhden arvon, koska jokaisella arvolla on oma numeronsa.

Jos tarvitset kolme arvoa, voit sanoa:

Arvo1="yksi"; arvo2="kaksi"; arvo3="kolme";

TAI voit käyttää

Arvot="yksi"; arvot="kaksi"; arvot="kolme";

Ensimmäinen esimerkki on kolme eri muuttujaa, joilla on omat nimensä (jotka eroavat yhden merkin verran). Toinen esimerkki on taulukko, joka koostuu yhdestä muuttujasta, mutta sisältää useita arvoja, joista jokaisella on oma numeronsa.

Kun muuttujaa käytetään taulukkona, arvo on aina lisättävä hakasulkeisiin. Voit valita taulukkomuuttujalle minkä tahansa nimen, mutta tästä lähtien sitä voidaan käyttää VAIN taulukossa. Et VOI tehdä merkityksellisiä asioita

Arvot="yksi"; value="newvalue";

Voit kuitenkin määrittää arvoja uudelleen samalla tavalla kuin tavallisille muuttujille. Nuo. seuraava on oikein:

Arvot="1"; tulostaa arvot; arvot="yksi"; tulostaa arvot;

Mielenkiintoista on, että toisin kuin jotkut muut kielet, sinun ei tarvitse käyttää vain numeroita. Yllä olevissa esimerkeissä ,, tulkitaan itse asiassa ["1"], ["2"], ["3"]. Tämä tarkoittaa, että voit käyttää myös muita merkkijonoja tunnisteina ja käsitellä taulukkoa melkein kuin yksisarakkeista tietokantaa. Tämän virallinen nimi on "assosioitu array".

Numerot["yksi"]=1; numerot["kaksi"]=2; tulosta numerot ["yksi"]; value="two"; print numbers; value=$1; if(numbers = ""){ print "no such number"; } !}

Milloin ja miten taulukoita käytetään

Saattaa olla useita tapauksia, joissa voit valita taulukoiden käyttämisen. Jotkut ihmiset tekevät awkin kanssa ilman taulukoita ollenkaan. Mutta tämä ei ole täysin oikea sijainti: taulukoille on erityisiä muuttujia, jotka osoittavat esimerkiksi sen koon (arvojen lukumäärä taulukossa), on olemassa rakenteita, jotka ovat käteviä taulukon jäsenten luettelemiseen, ja jotkut funktiot palauttavat arvon taulukon muodossa. Joka tapauksessa, katsotaanpa joitain esimerkkejä, joista voi olla hyötyä.

Tietojen tallentaminen myöhempää käyttöä varten

Kun käytät awk-ohjelmaa suuressa komentosarjassa, voit tallentaa tiedot väliaikaiseen tiedostoon. Mutta voit tallentaa tarvitsemasi sanat muistiin ja tulostaa ne kaikki lopussa, mikä on nopeampaa kuin väliaikaisen tiedoston käyttäminen.

/special/( tallennetut sanat=$2; lm+=1; ) END ( count=0; while(tallennetut sanat != "") ( tulostusmäärä,tallennetut sanat; count+=1; ) )

Sen sijaan, että vain näyttäisit sanat, voit käyttää LOPPU-osiota tehdäksesi tarvittavat lisäkäsittelyt ennen niiden näyttämistä.

Jos haluat määrittää arvoille ainutlaatuisen indeksin (päällekkäisyyksien välttämiseksi), voit yleensä viitata niiden arvoihin niiden omilla riveillä. Tai esimerkiksi tallenna taulukko sarakkeella 3, joka on indeksoitu sarakkeen 2 vastaavalla arvolla.

( threecol[$2]=$3 ) END ( for (v in threecol) ( tulosta v, threecol[v] ) )

Taulukot ja split()

Toinen tärkein syy taulukoiden käyttämiseen on, jos haluat tehdä alikenttiä. Oletetaan, että sinulla on rivi, jossa on useita suuria jakoja ja useita pieniä jakoja. Toisin sanoen ylimmän tason kentät erotetaan välilyönnillä, mutta silloin saat pienempiä sanoja erotettuina kaksoispisteillä.

Tämä on muuttuja:field:type-rivi. Tässä voi olla useita:type:arvoja

Yllä olevassa esimerkissä neljännessä välilyönnillä erotetussa kentässä on kaksoispisteillä erotettuja alikenttiä. Oletetaan nyt, että haluat tietää toisen alikentän arvon neljännessä suuressa kentässä. Yksi tapa tehdä tämä on kutsua kahta putkella yhdistettyä awkia:

Awk "(tulosta 4 dollaria)" | awk -F: "(tulosta 2 dollaria)"

Toinen tapa olisi muuttaa "FS":n arvoa lennossa, joka sisältää kenttäerottimen (ilmeisesti tämä ei toimi kaikissa awk-toteutuksissa):

Awk "( rivinvaihto=$4; fs=FS; FS=":"; $0=uusirivi; tulosta $2 ; FS=fs; )"

Mutta voit tehdä tämän myös taulukoilla käyttämällä split()-funktiota seuraavasti:

Awk "( rivinvaihto=$4; split(uusirivi,alikentät,":"); tulosta alikentät) "

Tässä tapauksessa taulukon käyttö on yleisin ja ehkä tyylikkäin tapa tehdä se.

Joten Awk tarjoaa rajoitetun määrän tietorakenteita. Skalaari- ja merkkijonomuuttujien lisäksi kielessä on sisäänrakennettu massiivinen tietorakenne. Vaikka tätä rakennetta kutsutaan virallisesti "taulukoiksi", se on itse asiassa siihen liittyvä taulukko, joka on samanlainen kuin Pythonin sanelutietorakenne.

Tauluja ei tarvitse alustaa. Voit vain aloittaa arvojen määrittämisen. Huomaa, että näppäimet voivat olla numeroita tai merkkijonoja.

Awk "BEGIN ( \ a = 1.1; \ a = 0; \ a["KOIRA"] = "KISSA"; \ print a, a, a["KOIRA"] \ )" 1.1 0 CAT

Awk ei tulosta muuttujaa ilman indeksiä:

Awk "BEGIN ( \a["DOG"] = "KISSA"; \print a\ )" awk: cmd. rivi:3: kohtalokas: yritä käyttää taulukkoa "a" skalaarikontekstissa

Vaikka voimme silmukan avaimella käyttämällä varten:

Awk "BEGIN ( \ a = 1.1; \ a = 0; \ a["DOG"] = "KISA"; \ for(k in a) print(a[k]) \ )" CAT 0 1.1

Osa 7: AWK ja Shells (sh/ksh/bash/csh)

Joskus AWK:n toiminnallisuus ei ehkä riitä. Tässä tapauksessa voit integroida awk:n shell-skriptiisi. Alla on esimerkkejä siitä, kuinka tämä voidaan tehdä.

Yksinkertainen päätelmä

Joskus haluat käyttää awk-komentoa vain muotoilijana ja tyhjentää tulosteen suoraan käyttäjälle. Seuraava komentosarja ottaa käyttäjänimen argumenttina ja käyttää awk-komentoa käyttäjän tietojen poistamiseen tiedostosta /etc/passwd.

Huomautus: Huomaa, että skriptissä yksittäiset lainausmerkit ovat laajennettuja (ei sisäkkäisiä) ja kahden laajennetun yksittäislainausparin välissä on muuttuja $1 (toinen), joka tässä tapauksessa on komentosarjan argumentti, kun taas $1 on osa syntaksia. $1 (tarkoittaa rivin ensimmäistä kenttää).

#!/bin/sh while [ "$1" != "" ] ; do awk -F: "$1 == ""$1"" ( tulosta $1,$3) " /etc/passwd shift valmis

awk-ulostulokuoren muuttujien määrittäminen

Joskus haluamme käyttää awk-komentoa vain nopeaan tapaan asettaa muuttujan arvo. Paswd-teeman avulla voimme selvittää käyttäjälle kuoren ja tarkistaa, onko se virallisten komentotulkkien luettelossa.

Huomaa jälleen, kuinka yksittäiset lainausmerkit suljetaan awk-lausekkeessa Suljetun (toisen) lainauksen jälkeen $1 on muuttuja, joka välitetään komentosarjalle ensimmäisen argumentin arvo, ei osa awk-syntaksia.

#!/bin/sh user="$1" if [ "$user" == "" ] ; sitten echo ERROR: tarvitset käyttäjätunnuksen ; poistu ; fi usershell=`awk -F: "$1 == ""$1"" ( tulosta $7) " /etc/passwd` grep -l $usershell /etc/shells jos [ $? -ne 0]; sitten echo ERROR: shell $usershell käyttäjälle $user ei /etc/shells fi

Muita vaihtoehtoja:

# Katso "man regex" usershell=`awk -F: "/^"$1":/ ( tulosta $7) " /etc/passwd` echo $usershell; # Vain moderni awk hyväksyy -v. Saatat joutua käyttämään "nawk" tai "gawk" userhell2=`awk -F: -v user=$1 "$1 == user ( tulosta $7) " /etc/passwd` echo $usershell2;

Lisämenetelmien selittäminen yllä jää lukijalle kotitehtäväksi :)

Tietojen siirto awk:iin putken kautta

Joskus haluat laittaa awk:n datasuodattimeksi, suureen ohjelmaan tai komentotulkkikehotteeseen syötetyksi yksiriviksi. Esimerkki tällaisesta komennosta komentosarjassa (luettelo verkkopalvelimen lokitiedostoista välitetään komentosarjan argumentteina, koska lokikirjaus on muokattavissa ja lokeilla voi olla erilainen rakenne; jotta se toimisi tietyissä tapauksissa, se voi on tarpeen säätää komentoja):

#!/bin/sh grep -h " /index.html" $* | awk -F\" "(tulosta 4 dollaria)" | lajittele -u

  1. Mielenkiintoinen artikkeli, haluan kiittää sinua ponnisteluistasi.

    Huomasin sen olevan epätarkka. Jos suoritat rivin esimerkistä

    Awk -F " " "( tulosta $2 )" field_data.txt

    se tulostaa saman asian kuin

    Awk "( tulosta $2 )" field_data.txt

    Tuloksena on esimerkki -F ei hyvin kuvattu.

AWK(1)

NIMI
awk - kuvioiden sovitus ja tekstin muunnos

SYNTAKSI

Awk [-Fsymbol] [[-f] ohjelma] [argumentti...] [tiedosto...]

KUVAUS
awk-komento kohdistaa lähdetiedostojen rivit ohjelmassa määritettyihin malleihin. Mallit voidaan määrittää joko suoraan komentorivillä tai sijoittaa tiedostoon nimeltä ohjelma ja käyttää -f-vaihtoehtoa. Jos mallit on määritetty komentorivillä, ne tulee laittaa lainausmerkkeihin ("), jotta komentotulkki ei tulkitse niitä.

awk-komento voidaan välittää argumentteja muodossa x=... y=... jne. (katso ESIMERKKEJÄ).

Tiedostot luetaan niiden antamisjärjestyksessä. Jos tiedostoa ei ole määritetty tai nimi on -, käytetään vakiosyöttöä. Awk-syöte on jaettu erikoismerkillä erotettuihin merkintöihin. Oletusasetus on rivinsyöttö; tässä tapauksessa awk käsittelee syötteen rivi riviltä. Tietueen erotinta voidaan muuttaa ohittamalla RS-muuttuja. Jokainen tietue on jaettu kenttiin, jotka on rajattu kenttäerottimella (oletuksena välilyönnit). Tätä erotinta voidaan muuttaa määrittämällä FS-muuttuja uudelleen tai määrittämällä -Fcharacter-lippu. Lähderivikentät ovat käytettävissä nimillä $1, $2,...; $0 on koko syötemerkkijono.

Jokaiselle ohjelman mallille voidaan määrittää toiminto, joka suoritetaan mille tahansa merkkijonolle, joka on onnistuneesti sovitettu malliin. Mallitoiminto-operaattorilla on muoto:

Pattern ( action ) Jokainen lähdemerkkijono yhdistetään jokaiseen malliin; jos onnistuu, määritetyt toiminnot suoritetaan. Kun kaikki kuviot on sovitettu, syötetään seuraava rivi ja sovitusprosessi toistetaan. Joko kuvio tai toiminto voidaan jättää pois, mutta ei molempia. Jos tietylle kuviolle ei ole määritetty toimintoa, rivi yksinkertaisesti kopioidaan vakiotulostukseen. Jos toiminnolle ei ole määritetty kuviota, se suoritetaan jokaiselle syöttöriville. Rivit, jotka eivät vastaa mitään kuviota, ohitetaan.

Toiminto on lauseiden sarja. Koska mallit ja toiminnot voidaan jättää pois, niiden erottamiseksi ohjelmassa jälkimmäinen on suljettava aaltosulkeilla. Operaattori on yksi rakenteista:

If (ehto) lauseke [ else lauseke ] while (ehto) lauseke (lauseke; ehto; lauseke) lause break jatka ( [ lauseke ] ... ) muuttuja = lauseke print [ lausekeluettelo ] [> lauseke ] printf muoto [, lausekeluettelo ] [> lauseke ] seuraava # ohita jäljellä olevat kuviot ja siirry seuraavalle riville poistu # ohita jäljellä olevat rivit

Lausunnot päätetään puolipisteellä, rivinvaihdolla tai oikealla sululla. Tyhjä lausekeluettelo tarkoittaa koko merkkijonoa. Lausekkeet rakennetaan merkkijonoista ja numeroista käyttämällä operaatioita +, -, *, /, % ja ketjutusta (ilmaistaan ​​välilyönnillä). Voit myös käyttää C-kielen operaattoreita lausekkeissa: ++, --, +=, -=, *=, /=, %=. Muuttujat alustetaan tyhjillä merkkijonoilla. Muuttujat voivat olla skalaareja, taulukon elementtejä (merkitty x[i]) tai kenttiä. Taulukkoindeksit voivat olla mitä tahansa (ei välttämättä numeerisia) merkkijonoja, mikä mahdollistaa eräänlaisen assosiatiivisen muistin toteuttamisen. Merkkijonot on suljettu lainausmerkkeihin (").

Print-käsky tulostaa argumenttinsa vakiotulosteeseen (tai tiedostoon, jos >lauseke-osa on olemassa), erottaen ne nykyisellä kenttäerottimella ja päättäen jokaisen tietueen tulostietueen erottimella. Printf-käsky tekee saman asian, mutta muotosäädön alla [katso printf(3S)].

Sisäänrakennettu pituusfunktio palauttaa argumenttinsa pituuden ja käsittelee sitä merkkijonona; jos argumentti jätetään pois, palautetaan nykyisen rivin pituus. Myös seuraavat sisäänrakennetut funktiot on määritelty: exp, log, sqrt ja int (int hylkää murto-osa argumenttisi). Funktio substr(s, m, n) palauttaa n-merkkisen s:n osajonon, joka alkaa paikasta m. Funktio sprintf(format, lauseke, lauseke,...) muuntaa lausekkeet määritetyn muodon mukaan [katso printf(3S) ] ja palauttaa tuloksena olevan merkkijonon.

Malli on mielivaltainen looginen yhdistelmä, joka on muodostettu käyttämällä operaattoreita !, ||, && ja sulkuja säännöllisistä lausekkeista ja vertailulausekkeista. Säännöllisten lausekkeiden ympärillä on / [katso yksityiskohtia egrep(1)]. Yksittäinen säännöllinen lauseke kuviossa yhdistetään koko merkkijonoon. Myös säännöllisiä lausekkeita voidaan sisällyttää vertailulausekkeisiin. Kuvio voi koostua kahdesta pilkulla erotetusta kuviosta; tässä tapauksessa määritetyt toiminnot suoritetaan kaikille viivoille, jotka ovat ensimmäisen kuvion ja toisen kuvion täyttävän viivan välillä.

Vertailulauseke on yksi seuraavista rakenteista:

oper_compare lauseke säännöllinen_lauseke oper_compare lauseke

missä oper_compare on mikä tahansa kuudesta C-vertailuoperaattorista, oper_compare on ~ (sisältyy) tai !~ (ei sisällä).

Edellytys on aritmeettinen lauseke, vertailulauseke tai niiden looginen yhdistelmä.

Voit suorittaa minkä tahansa toiminnon ennen ensimmäistä tai sen jälkeen viimeinen rivi erityiset kuviot BEGIN ja END määritellään. BEGIN on oltava ensimmäinen malli, END on oltava viimeinen. Jos esimerkiksi haluat käyttää c-merkkiä kentän erottimena, voit joko ajaa ohjelman vaihtoehdolla -Fc tai määrittää

BEGIN ( FS = c ) Muut erikoismuuttujat: NF Kenttien lukumäärä nykyisessä tietueessa. NR Sarjanumero nykyinen merkintä. FILENAME Sen tiedoston nimi, josta Tämä hetki syöttö tehdään. OFS Tulostuksen kenttäerotin, oletuksena välilyönti. ORS Tietueen erotin ulostulolle, rivinsyöttö oletuksena. OFMT Numeron tulostusmuoto, oletus %.6g.

ESIMERKKEJÄ

  1. Tulosta rivit tiedostossa f1, jotka sisältävät yli 72 merkkiä: awk "length > 72" f1
  2. Tulosta tiedoston f2 kaksi ensimmäistä kenttää käänteisessä järjestyksessä: awk "( tulosta $2, $1 )" f2
  3. Lisää numerot tiedoston f3 ensimmäiseen sarakkeeseen, tulosta summa ja aritmeettinen keskiarvo:
    Prog-tiedostossa: ( s += $1 ) END ( tulosta "summa on", s, "keskiarvo on", s/NR ) Komentorivi: awk -f prog f3
  4. Tulosta tiedoston f4 kentät käänteisessä järjestyksessä: awk "( for (i = NF; i > 0; --i) tulosta $i )" f4
  5. Tulosta kaikki tiedoston f5 rivit aloitus/lopetus-parien välillä awk "/start/,/stop/" f5
  6. Tulosta ne tiedoston f6 rivit, joiden ensimmäinen kenttä ei vastaa edellisen rivin ensimmäistä kenttää: awk "$1 != prev ( print; prev = $1 )" f6
  7. Tulosta tiedosto f7 lisäämällä sanan "Sivu" jälkeen sivumäärä viidennestä alkaen:
    Prog-tiedostossa: /Page/ ( $2 = n++ ) ( print ) Komentorivi: awk -f prog n=5 f7

CM. MYÖS
egrep(1) , lex(1) , sed(1) .
printf(3S) Ohjelmoijan viitteessä.

Yllätyksiä
Syöttötilat eivät säily tulosteessa, jos kyseisen tietueen kenttiä on muutettu.

awk-komentokielessä ei ole nimenomaisia ​​muunnoksia merkkijonojen ja numeroiden välillä. Jos haluat käsitellä lauseketta numerona, lisää siihen 0; käsitelläksesi ketjuna, ketjuta se tyhjään ketjuun ""