Dit artikel gaat in op de mogelijkheden van awk, die gemakkelijker te gebruiken zijn nu u weet hoe u uw commando’s kunt structureren tot een uitvoerbaar script.
Logische operatoren en conditionals
U kunt de logische operatoren en (geschreven &&) en of (geschreven ||) gebruiken om specificiteit aan uw conditionals toe te voegen.
Om bijvoorbeeld alleen records te selecteren en af te drukken met de tekenreeks “paars” in de tweede kolom en een bedrag lager dan vijf in de derde kolom:
$2 == "purple" && $3 < 5 {print $1}
Als een record “paars” in kolom twee heeft, maar een waarde groter dan of gelijk aan 5 in kolom drie, dan wordt het niet geselecteerd.
Ook als een record aan de eis van kolom drie voldoet, maar in kolom twee geen “paars” heeft, wordt het niet geselecteerd.
Stel dat u elk record in uw bestand wilt selecteren waarvan het bedrag groter is dan of gelijk aan acht en een overeenkomend record met twee sterretjes (**) wilt afdrukken. U wilt ook elke record met een waarde tussen vijf (inclusief) en acht markeren met slechts één sterretje (*). Er zijn een paar manieren om dit te doen, en een manier is om het next commando te gebruiken om awk te instrueren dat nadat het een actie onderneemt, het moet stoppen met scannen en door moet gaan naar het volgende record.
Hier volgt een voorbeeld:
NR == 1 {
print $0;
next;
}
$3 >= 8 {
printf "%s\t%s\n", $0, "**";
next;
}
$3 >= 5 {
printf "%s\t%s\n", $0, "*";
next;
}
$3 < 5 {
print $0;
}
BEGIN commando
Met het BEGIN commando kunt u variabelen afdrukken en instellen voordat awk begint met het scannen van een tekstbestand. Zo kunt u bijvoorbeeld de scheidingstekens tussen invoer- en uitvoervelden in uw awk script instellen door ze in een BEGIN opdracht te definiëren. Dit voorbeeld past het eenvoudige script uit het vorige artikel aan voor een bestand met velden gescheiden door komma’s in plaats van spaties:
END commando
Het END commando, net als BEGIN, stelt u in staat om acties uit te voeren in awk nadat het scannen door het tekstbestand dat u aan het verwerken bent is voltooid. Als u cumulatieve resultaten van een waarde in alle records wilt afdrukken, kunt u dat pas doen nadat alle records zijn gescand en verwerkt.
De commando’s BEGIN en END worden elk slechts eenmaal uitgevoerd. Alle regels daartussen worden nul of meer keer op elk record uitgevoerd. Met andere woorden, het grootste deel van je awk script is een lus die wordt uitgevoerd bij elke nieuwe regel van het tekstbestand dat je verwerkt, met uitzondering van de BEGIN en END regels, die voor en na de lus worden uitgevoerd.
Hier volgt een voorbeeld dat niet mogelijk zou zijn zonder het END commando. Dit script accepteert waarden uit de uitvoer van het Unix commando df en verhoogt twee aangepaste variabelen (used en available) met elk nieuw record.
$1 != "tempfs" {
used += $3;
available += $4;
}
END {
printf "%d GiB used\n%d GiB available\n", used/2^20, available/2^20;
}
Sla het script op als total.awk en probeer het:
df -l | awk -f total.awk
De used en available variabelen gedragen zich als variabelen in veel andere programmeertalen. Je maakt ze willekeurig en zonder hun type te declareren, en je voegt er naar believen waarden aan toe. Aan het eind van de lus telt het script de records in de respectievelijke kolommen bij elkaar op en drukt de totalen af.
Wiskunde
Zoals je waarschijnlijk wel kunt zien aan alle logische operatoren en toevallige berekeningen tot nu toe, doet awk wiskunde heel natuurlijk. Dit maakt het misschien wel een erg handige rekenmachine voor uw terminal. In plaats van moeite te doen om de nogal ongebruikelijke syntaxis van bc te onthouden, kun je gewoon awk gebruiken samen met zijn speciale BEGIN functie om de vereiste van een bestandsargument te vermijden:
$ awk 'BEGIN { print 2*21 }'
42
$ awk 'BEGIN {print 8*log(4) }'
11.0904
Toegegeven, dat is nog steeds veel typewerk voor eenvoudige (en niet zo eenvoudige) wiskunde, maar het zou niet veel moeite kosten om een frontend te schrijven, wat een oefening voor je is om te onderzoeken.
Dit artikel is overgenomen van een aflevering van Hacker Public Radio, een technologie podcast.