awk-funktiot, printf-muotoilu ja raporttien tuottaminen
Määritä omia funktioita ja käytä printf-komentoa viimeisteltyjen taulukkomuotoisten raporttien tuottamiseen raakadatavirroista.
awk-funktiot, printf-muotoilu ja raporttien tuottaminen on ilmainen Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Linux-komentorivin ja Bash-komentosarjojen hallinta-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssilla on yhteensä 4 oppituntia.
Miksi funktiot ja printf ovat tärkeitä awk:ssa
Kun awk-ohjelmasi kasvavat yhden rivin komennoista usean vaiheen putkiksi, kaksi ominaisuutta muuttuu välttämättömäksi: käyttäjän määrittämät funktiot ja printf-muotoilu.
Funktioiden avulla voit kapseloida uudelleenkäytettävän logiikan – kuten prosenttilaskurin, merkkijonon trimmaajan tai yksikkömuuntimen – ja kirjoittaa sen kerran, minkä jälkeen voit kutsua sitä missä tahansa saman ohjelman kohdassa. printf-komennolla voit hallita täsmällisesti tulosteen ulkoasua: sarakkeiden leveyksiä, desimaaleja, täytemerkkejä ja tasausta.
Yhdessä ne muuttavat raakatiedot sisältävät lokirivit viimeistellyiksi ja helppolukuisiksi raporteiksi, joiden perusteella insinöörit ja esihenkilöt voivat toimia.
- Funktiot vähentävät toistoa ja helpottavat ohjelmien testaamista erillään.
printftasaa tiedot vakiomittaisiin sarakkeisiin, joten raportit säilyvät luettavina myös syötteen pituuksien vaihdellessa.- Molemmat ominaisuudet toimivat ympäristöissä POSIX awk, gawk ja mawk – laajennuksia ei tarvita.
Käyttäjän määrittämän funktion määrittäminen awk:ssa
Käyttäjän määrittämä funktio ilmoitetaan avainsanalla function ennen kuvio-toiminto-sääntöjä tai niiden jälkeen. Syntaksi on seuraava:
function name(param1, param2, local1, local2) {
# body
return value
}Keskeinen awk-idiomi: paikalliset muuttujat ovat yksinkertaisesti ylimääräisiä parametreja, joiden edellä on ylimääräisiä välilyöntejä. local-avainsanaa ei ole – ylimääräisten välilyöntien käytäntö ilmaisee, että kyseiset parametrit ovat paikallisia eivätkä kutsuvan koodin välittämiä argumentteja.
- Kaikki muuttujat, joita ei ilmoiteta parametreiksi, ovat oletusarvoisesti globaaleja.
- Funktiot voivat kutsua itseään rekursiivisesti.
returnon valinnainen; ilman sitä funktio palauttaa tyhjän merkkijonon.
#!/usr/bin/env bash
# Demonstrate a simple awk user function
echo '10 3
7 0
100 4' | awk '
function divide(a, b, result) {
if (b == 0) return "ERR"
result = a / b
return result
}
{
print $1 "/" $2 " = " divide($1, $2)
}
'Funktiot ja merkkijonologiikka
Funktiot ovat erityisen hyödyllisiä toistuvissa merkkijono-operaatioissa. Ajatellaan alku- ja loppupään tyhjeiden poistamista – raakalokidatassa sitä tarvitaan usein ennen vertailua tai raportointia.
Alla oleva esimerkki määrittää funktion trim(s) käyttäen gsub-funktiota ja käyttää sitä jokaisessa tietueessa, jolloin pääsääntö pysyy siistinä ja helppolukuisena.
gsub(regex, replacement, target)muokkaa target-arvoa paikallaan ja palauttaa korvausten määrän.- Sijoittamalla säännöllisen lausekkeen logiikan funktion sisään sääntölohko voi keskittyä liiketoimintalogiikkaan.
- Voit tehdä yksikkötestejä välittämällä itse laadittuja merkkijonoja suoraan
BEGIN-lohkossa.
#!/usr/bin/env bash
# trim() strips leading/trailing spaces; used to normalise CSV-like data
printf ' alice , 90 \n bob , 85 \n carol , 92 \n' | awk -F',' '
function trim(s) {
gsub(/^[ \t]+|[ \t]+$/, "", s)
return s
}
{
name = trim($1)
score = trim($2)
print name, score
}
'printf:n esittely awk:ssa
awk:n printf noudattaa samoja käytäntöjä kuin C ja Bashin sisäinen printf. Keskeinen ero print-komentoon on, että printf ei koskaan lisää rivinvaihtoa automaattisesti – sinun on lisättävä \n itse.
Yleisiä muotoilumääritteitä:
%s– merkkijono%d– kokonaisluku%f– liukuluku%e– tieteellinen merkintätapa%g– lyhyempi vaihtoehdoista%f/%e
Leveyttä ja tarkkuutta säädetään sijoittamalla numerot merkin % ja määritteen väliin: %-20s tasaa merkkijonon vasemmalle 20 merkin kentässä; %8.2f tuottaa 8 merkin levyisen liukuluvun kahdella desimaalilla.
#!/usr/bin/env bash
# printf format specifiers in awk
echo '' | awk '
BEGIN {
printf "%s\n", "plain string"
printf "%10s\n", "right-pad"
printf "%-10s|\n", "left-pad"
printf "%8.2f\n", 3.14159
printf "%08d\n", 42
printf "%e\n", 123456.789
}
'Raportin otsikon rakentaminen printf:llä
Viimeistelty raportti tarvitsee otsikkorivin ja erotinviivan. BEGIN-lohko on luonteva paikka niiden tulostamiseen – se suoritetaan kerran ennen minkään syötteen käsittelyä.
Temppu on sovittaa leveydet otsikossa täsmälleen tietoriveillä käytettyihin leveyksiin. Leveysvakioiden määrittäminen BEGIN-lohkossa (tai funktiossa) pitää kaiken synkronoituna, kun muutat sarakkeiden leveyksiä myöhemmin.
- Piirrä erotinviiva käyttämällä
printf-komentoa ja viivoista koostuvaa erotinmerkkijonoa. - Päätä otsikkorivit aina merkkeihin
\n. - Yhdistä täydelliseksi raporttirakenteeksi
BEGIN-otsikko, tietuekohtaiset rivit jaEND-alatunniste.
#!/usr/bin/env bash
# Print a report header in BEGIN, data rows per-record, total in END
printf 'alice 9200 12\nbob 8750 10\ncarol 10400 14\n' | awk '
BEGIN {
printf "%-10s %10s %6s %12s\n", "Name", "Salary", "Months", "Annual"
printf "%s\n", "----------------------------------------------"
total = 0
}
{
annual = $2 * $3
total += annual
printf "%-10s %10d %6d %12d\n", $1, $2, $3, annual
}
END {
printf "%s\n", "----------------------------------------------"
printf "%-10s %10s %6s %12d\n", "TOTAL", "", "", total
}
'Käyttäjän määrittämät funktiot muotoilulogiikkaa varten
Kun rakennat usean sarakkeen raportteja, samaa muotoilukutsua tarvitaan usein useassa paikassa – esimerkiksi prosenttipalkin piirtämiseen tai tavujen muuntamiseen ihmiselle helppolukuiseksi yksiköksi. Kun sijoitat tämän funktion sisään, vältät toiston ja voit muuttaa muotoilua helposti kaikkialla.
Alla oleva funktio muuntaa tavut kilotavuiksi, megatavuiksi tai gigatavuiksi ja palauttaa muotoillun merkkijonon. Kutsuva sääntö välittää funktiolle yksinkertaisesti $NF-arvon (viimeisen kentän) ja tulostaa palautuvan arvon.
#!/usr/bin/env bash
# human_bytes() converts raw byte counts to KB/MB/GB strings
printf 'var.log 1024\naccess.log 2097152\ncore.dump 1073741824\ntiny.txt 512\n' | awk '
function human_bytes(n, s) {
if (n >= 1073741824) { s = sprintf("%.1f GB", n/1073741824) }
else if (n >= 1048576) { s = sprintf("%.1f MB", n/1048576) }
else if (n >= 1024) { s = sprintf("%.1f KB", n/1024) }
else { s = sprintf("%d B", n) }
return s
}
BEGIN { printf "%-20s %10s\n", "File", "Size"; print "------------------------------" }
{ printf "%-20s %10s\n", $1, human_bytes($2) }
'Tietojen kerääminen taulukoihin ennen tulostamista
Oikeissa raporteissa tarvitaan usein summia, keskiarvoja tai järjestyksiä — arvoja, joita ei voi laskea ennen kuin kaikki syöte on nähty. Toimintamalli on seuraava:
- Kerätkää tiedot assosiatiivisiin taulukoihin tietuekohtaisen käsittelyn aikana.
- Laskekaa johdetut arvot (keskiarvot, prosenttiosuudet)
END-lohkossa. - Tulostakaa muotoiltu tulos vain
END-lohkosta, jotta sarakeleveydet voivat mukautua koko aineistoon.
Tämä viivästetyn tulostuksen toimintamalli on yksi awk-raporttien tehokkaimmista idiomeista. Alla oleva esimerkki laskee pyyntöjen määrät ja vastaus tavujen määrät HTTP-tilakoodien mukaan access-lokista.
#!/usr/bin/env bash
# Summarise an nginx-style access log by HTTP status code
printf '127.0.0.1 200 1234\n127.0.0.1 404 512\n10.0.0.2 200 8900\n10.0.0.3 500 256\n10.0.0.4 200 4096\n10.0.0.5 404 300\n' | awk '
{
status = $2
bytes = $3
count[status]++
total_bytes[status] += bytes
}
END {
printf "%-8s %8s %14s\n", "Status", "Requests", "Total Bytes"
print "-----------------------------------"
for (s in count)
printf "%-8s %8d %14d\n", s, count[s], total_bytes[s]
}
'Rekursiiviset funktiot awk-kielessä
awk tukee rekursiota. Tyypillisiä käyttötapauksia ovat kertomien laskeminen ja toistuvien merkkijonojen muodostaminen (esimerkiksi päätteen leveyden mukaisen viivajonon luominen). Rekursio on awk-kielessä harvinaisempaa kuin yleiskäyttöisissä ohjelmointikielissä, mutta se toimii oikein ja on käytettävissä kaikissa tärkeimmissä toteutuksissa.
Alla oleva esimerkki määrittelee rekursiivisen repeat(s, n)-funktion ja käyttää sitä erotinviivojen piirtämiseen niin, että viivat vastaavat automaattisesti leveimmän tietorivin leveyttä — kiinteästi määritettyjä viivoja ei tarvita.
- Välttäkää syvää rekursiota suurilla syötteillä — awk-kielessä ei ole häntärekursion optimointia.
- Yksinkertaiseen toistoon
sprintf("%*s", n, "")yhdessägsub(/ /, "-")-funktion kanssa on nopeampi mutta havainnollisuudeltaan heikompi vaihtoehto.
#!/usr/bin/env bash
# Recursive repeat() to build separator lines dynamically
awk '
function repeat(s, n, acc) {
if (n <= 0) return ""
acc = s repeat(s, n-1)
return acc
}
BEGIN {
header = sprintf("%-15s %10s %10s", "Metric", "Current", "Target")
sep = repeat("-", length(header))
print sep
print header
print sep
printf "%-15s %10.1f %10.1f\n", "CPU %", 72.4, 60.0
printf "%-15s %10.1f %10.1f\n", "Mem GB", 14.2, 16.0
printf "%-15s %10d %10d\n", "Open FDs", 1024, 800
print sep
}
' /dev/nullprintf-tulostus tiedostoon tai putkeen awk-kielessä
awkin printf (ja print) voi uudelleenohjata tulosteen tiedostoihin tai välittää sen putkella shell-komentoihin — suoraan awk-ohjelman sisältä ilman, että koko ohjelmaa tarvitsee sijoittaa alikuoreen.
printf "..." > "file.txt"— kirjoittaa tiedostoon (tyhjentää tiedoston kerran ja lisää sen jälkeen samaan tiedostoon suorituksen aikana).printf "..." >> "file.txt"— lisää tulosteen tiedoston loppuun.printf "..." | "sort -rn"— välittää tulosteen putkella shell-komennolle; awk pitää putken avoinna tietueiden käsittelyn ajan ja sulkee sen ohjelman lopussa.
Yleinen toimintamalli on jakaa lokin yksi läpikäynti useiksi tilan tai isännän mukaan määräytyviksi tulostetiedostoiksi, jolloin suurta tiedostoa ei tarvitse lukea toistuvasti.
#!/usr/bin/env bash
# Route records into per-status files using print redirection
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
printf '200 /index.html\n404 /missing\n200 /api/data\n500 /crash\n404 /lost\n' | awk -v out="$tmpdir" '
{
file = out "/" $1 ".log"
printf "%-6s %s\n", $1, $2 > file
}
END {
close(file) # flush all open handles
}
'
echo "=== 200 ==="
cat "$tmpdir/200.log"
echo "=== 404 ==="
cat "$tmpdir/404.log"CSV-raportin luominen awk-kielellä
Kaikkia raportteja ei ole tarkoitettu ihmisille. Joskus tulosteen on oltava koneellisesti luettavaa CSV-muotoa, joka syötetään taulukkolaskentaohjelmaan tai seuraavaan käsittelyputkeen. awkin printf sopii tähän hyvin: asettakaa OFS-pilkuksi tai määrittäkää jokainen erotinmerkki erikseen.
Awk-kielellä tuotettavan toimivan CSV-tulosteen kaksi tärkeää sääntöä:
- Ympäröikää pilkkuja tai rivinvaihtoja mahdollisesti sisältävät kentät lainausmerkeillä.
- Escapettakaa kentän sisältämät kirjaimelliset lainausmerkit kaksinkertaistamalla ne:
He said ""hello"".
Alla oleva csv_field(s)-funktio kapseloi tämän lainausmerkkilogiikan, joten sitä voidaan käyttää yhdenmukaisesti kaikissa merkkijonokentissä.
#!/usr/bin/env bash
# Emit a valid CSV report from space-separated input
printf 'alice engineer 95000\nbob "sales,mgr" 82000\ncarol developer 110000\n' | awk '
function csv_field(s, safe) {
safe = s
gsub(/"/, "\"\"" , safe) # double any embedded quotes
return "\"" safe "\"" # wrap in quotes
}
BEGIN { print "Name,Role,Salary" }
{
printf "%s,%s,%d\n", csv_field($1), csv_field($2), $3
}
'Kokonainen esimerkki: täydellinen access-lokiraportti
Tämä viimeinen esimerkki kokoaa kaiken yhteen: käyttäjän määrittämät funktiot, printf-muotoilun, tietojen keräämisen taulukoihin sekä rakenteisen ylä- ja alatunnisteen. Syöte on yksinkertaistettu web-käyttöloki; tuloste on ihmisille tarkoitettu yhteenvetotaulukko, jossa on menetelmäkohtaiset summat ja loppusumman sisältävä rivi.
Keskeiset käytetyt tekniikat:
count[method]++jabytes[method] += sizekeräävät menetelmäkohtaiset tilastot yhdellä läpikäynnillä.human_bytes()(aiemmasta osiosta) muuntaa tavumäärät luettavaan muotoon.- Ylä-, data- ja alatunnisteessa samanlaisina käytetyt leveydet
printf-muotoilussa pitävät taulukon kohdistettuna syötteen koosta riippumatta. END-lohko käy taulukon läpi komennollafor (k in arr)ja tulostaa järjestetyn tuloksen putkea pitkin komennollesort.
#!/usr/bin/env bash
# Full access log report: method breakdown with human-readable bytes
printf 'GET /index 200 4096\nPOST /api 201 512\nGET /img 200 102400\nDELETE /item 204 0\nPOST /login 401 256\nGET /style 200 8192\n' | awk '
function human_bytes(n, s) {
if (n >= 1048576) s = sprintf("%.1f MB", n/1048576)
else if (n >= 1024) s = sprintf("%.1f KB", n/1024)
else s = sprintf("%d B", n)
return s
}
{
method = $1
size = $4
count[method]++
bytes[method] += size
grand_count++
grand_bytes += size
}
END {
fmt = "%-10s %8s %15s\n"
sep = "----------------------------------"
printf fmt, "Method", "Requests", "Bytes"
print sep
for (m in count)
printf "%-10s %8d %15s\n", m, count[m], human_bytes(bytes[m])
print sep
printf "%-10s %8d %15s\n", "TOTAL", grand_count, human_bytes(grand_bytes)
}
'Tietotesti: paikalliset muuttujat awkin funktioissa
Millä seuraavista tavoista result ilmoitetaan oikein paikalliseksi muuttujaksi awk-funktion sisällä POSIX-käytännön mukaisesti?
Oppitunnin yhteenveto: awkin funktiot, printf ja raporttien luominen
Tässä oppitunnissa opitte kirjoittamaan tuotantolaatuisia awk-ohjelmia, jotka luovat muotoiltuja raportteja raakadatan virroista. Tässä tärkeimmät asiat, jotka kannattaa pitää mielessä:
- Käyttäjän määrittämät funktiot ilmoitetaan muodossa
function name(params, locals). Paikallisia muuttujia edeltävät ylimääräiset välilyönnit ovat POSIX-käytäntö —local-avainsanaa ei ole. - printf tarjoaa tarkan tulosteen hallinnan: leveyden (
%10s), kohdistuksen (%-10s) ja tarkkuuden (%8.2f). Muistakaa lisätä\nerikseen. - Käyttäkää BEGIN-lohkoa ylä- ja erotinrivien tulostamiseen, tietuekohtaisia sääntöjä tietojen keräämiseen ja END-lohkoa summien laskemiseen sekä valmiin raportin tulostamiseen.
- Uudelleenohjatkaa
printf-tuloste tiedostoihin (> file) tai putkiin (| "sort") awkin sisältä raporttien jakamiseksi tai tulosteen jatkokäsittelyä varten. - Ympäröikää merkkijonokentät csv_field()-apufunktiolla CSV-tulosteen luonnin yhteydessä, jotta kenttien sisältämät pilkut ja lainausmerkit käsitellään turvallisesti.
- Yksiköitä muuntavat (
human_bytes), merkkejä toistavat (repeat) tai merkkijonoja puhdistavat (trim,csv_field) funktiot kannattaa säilyttää omassa awk-kirjastossa — niitä voi yhdistellä sujuvasti eri projekteissa.
Opi Bash tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 22
- Oppitunnit
- 88
Usein kysytyt kysymykset
Onko oppitunti ”awk-funktiot, printf-muotoilu ja raporttien tuottaminen” ilmainen?
Kyllä – oppitunnin ”awk-funktiot, printf-muotoilu ja raporttien tuottaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssin, päivitä CoddyKit PROhon. Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”awk-funktiot, printf-muotoilu ja raporttien tuottaminen”?
Määritä omia funktioita ja käytä printf-komentoa viimeisteltyjen taulukkomuotoisten raporttien tuottamiseen raakadatavirroista. Harjoittelet Linux-komentorivin ja Bash-komentosarjojen hallinta-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Linux-komentorivin ja Bash-komentosarjojen hallinta-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Linux-komentorivin ja Bash-komentosarjojen hallinta-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”awk-funktiot, printf-muotoilu ja raporttien tuottaminen”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunnilla?
Kyllä. Jokainen Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Tietueet, kentät ja mukautetut erottimet awk-ohjelmassa
- Mallit, alueet ja BEGIN- ja END-lohkot
- Koostaminen awk-taulukoilla ja ryhmittely
- awk-funktiot, printf-muotoilu ja raporttien tuottaminen