
Op Linux, awk
is een dynamo voor tekstmanipulatie op de opdrachtregel, evenals een krachtige scripttaal. Hier is een inleiding tot enkele van de coolste functies.
Hoe vreemd kreeg zijn naam
De awk
commando werd genoemd met de initialen van de drie mensen die de originele versie in 1977 schreven: Alfred Aho, Peter Weinberger en Brian Kernighan. Deze drie mannen waren afkomstig uit het legendarische AT&T Bell Laboratories Unix-pantheon. Met de bijdragen van vele anderen sindsdien, awk
is blijven evolueren.
Het is een volledige scripttaal, evenals een complete toolkit voor tekstmanipulatie voor de opdrachtregel. Als dit artikel je eetlust opwekt, kun je er elk detail over lezen awk
en zijn functionaliteit.
Regels, patronen en acties
awk
werkt aan programma’s die regels bevatten die uit patronen en acties bestaan. De actie wordt uitgevoerd op de tekst die overeenkomt met het patroon. Patronen staan tussen accolades ({}
). Een patroon en een handeling vormen samen een regel. De hele awk
programma staat tussen enkele aanhalingstekens ('
).
Laten we eens kijken naar het eenvoudigste type awk
programma. Het heeft geen patroon, dus het komt overeen met elke regel tekst die erin wordt ingevoerd. Dit betekent dat de actie op elke regel wordt uitgevoerd. We zullen het gebruiken op de uitvoer van de who
opdracht.
Hier is de standaarduitvoer van who
:
who
Misschien hebben we niet al die informatie nodig, maar willen we gewoon de namen op de rekeningen zien. We kunnen de output van who
in awk
, en vertel het dan awk
om alleen het eerste veld af te drukken.
Standaard, awk
beschouwt een veld als een reeks tekens omgeven door witruimte, het begin van een regel of het einde van een regel. Velden zijn te herkennen aan een dollarteken ($
) en een nummer. Zo, $1
vertegenwoordigt het eerste veld, dat we zullen gebruiken met de print
actie om het eerste veld af te drukken.
We typen het volgende:
who | awk '{print $1}'
awk
drukt het eerste veld af en verwijdert de rest van de regel.
We kunnen zoveel velden afdrukken als we willen. Als we een komma als scheidingsteken toevoegen, awk
drukt een spatie tussen elk veld af.
We typen het volgende om ook de tijd af te drukken waarop de persoon heeft ingelogd (veld vier):
who | awk '{print $1,$4}'
Er zijn een aantal speciale veld-ID’s. Deze vertegenwoordigen de hele regel tekst en het laatste veld in de regel tekst:
- $ 0: Vertegenwoordigt de hele regel tekst.
- $ 1: Vertegenwoordigt het eerste veld.
- $ 2: Vertegenwoordigt het tweede veld.
- $ 7: Vertegenwoordigt het zevende veld.
- $ 45: Vertegenwoordigt het 45ste veld.
- $ NF: Staat voor “aantal velden” en vertegenwoordigt het laatste veld.
We typen het volgende om een klein tekstbestand te openen met een korte quote die wordt toegeschreven aan Dennis Ritchie:
cat dennis_ritchie.txt
Wij willen awk
om het eerste, tweede en laatste veld van de quote af te drukken. Merk op dat, hoewel het in het terminalvenster is gewikkeld, het slechts een enkele regel tekst is.
We typen het volgende commando:
awk '{print $1,$2,$NF}' dennis_ritchie.txt
We kennen die “eenvoud” niet. is het 18e veld in de tekstregel, en het kan ons niet schelen. Wat we wel weten, is dat het het laatste veld is en dat we kunnen gebruiken $NF
om zijn waarde te krijgen. De punt wordt gewoon als een ander personage in het lichaam van het veld beschouwd.
Scheidingstekens voor uitvoervelden toevoegen
U kunt het ook zien awk
om een bepaald teken tussen velden af te drukken in plaats van het standaard spatie-teken. De standaarduitvoer van het date
commando is ietwat vreemd omdat de tijd er midden in zit. We kunnen echter het volgende typen en gebruiken awk
om de velden te extraheren die we willen:
date
date | awk '{print $2,$3,$6}'
We gebruiken de OFS
(uitvoerveldscheidingsteken) variabele om een scheidingsteken tussen de maand, de dag en het jaar te plaatsen. Merk op dat we hieronder de opdracht tussen enkele aanhalingstekens ('
), geen accolades ({}
):
date | awk 'OFS="https://www.howtogeek.com/" {print$2,$3,$6}'
date | awk 'OFS="-" {print$2,$3,$6}'
De regels BEGIN en END
EEN BEGIN
regel wordt eenmaal uitgevoerd voordat de tekstverwerking begint. In feite is het eerder uitgevoerd awk
leest zelfs elke tekst. Een END
regel wordt uitgevoerd nadat alle verwerking is voltooid. U kunt er meerdere hebben BEGIN
en END
regels, en ze zullen in volgorde worden uitgevoerd.
Voor ons voorbeeld van een BEGIN
regel, we zullen de volledige quote van de dennis_ritchie.txt
bestand dat we eerder gebruikten met een titel erboven.
Om dit te doen, typen we dit commando:
awk 'BEGIN {print "Dennis Ritchie"} {print $0}' dennis_ritchie.txt
Merk op BEGIN
regel heeft zijn eigen reeks acties ingesloten in zijn eigen reeks accolades ({}
).
We kunnen dezelfde techniek gebruiken met het commando dat we eerder gebruikten om uitvoer van te pijpen who
in awk
. Om dit te doen, typen we het volgende:
who | awk 'BEGIN {print "Active Sessions"} {print $1,$4}'
Scheidingstekens voor invoervelden
Als je wil awk
om te werken met tekst die geen witruimte gebruikt om velden te scheiden, moet je hem vertellen welk teken de tekst gebruikt als veldscheidingsteken. Bijvoorbeeld de /etc/passwd
bestand gebruikt een dubbele punt (:
) om velden te scheiden.
We gebruiken dat bestand en de -F
(scheidingstekenreeks) optie om te vertellen awk
om de dubbele punt te gebruiken (:
) als scheidingsteken. We typen het volgende om te vertellen awk
om de naam van het gebruikersaccount en de basismap af te drukken:
awk -F: '{print $1,$6}' /etc/passwd
De uitvoer bevat de naam van het gebruikersaccount (of de naam van de applicatie of daemon) en de thuismap (of de locatie van de applicatie).
Patronen toevoegen
Als alles waar we in geïnteresseerd zijn gewone gebruikersaccounts zijn, kunnen we een patroon toevoegen aan onze afdrukactie om alle andere items eruit te filteren. Omdat gebruikers-ID-nummers gelijk zijn aan of groter zijn dan 1.000, kunnen we ons filter op die informatie baseren.
We typen het volgende om onze afdrukactie alleen uit te voeren wanneer het derde veld ($3
) bevat een waarde van 1.000 of hoger:
awk -F: '$3 >= 1000 {print $1,$6}' /etc/passwd
= 1000 {print $ 1, $ 6}’ / etc / passwd” commando in een terminalvenster.” width=”646″ height=”147″ onload=”pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);” onerror=”this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”>
Het patroon moet onmiddellijk voorafgaan aan de actie waaraan het is gekoppeld.
We kunnen de BEGIN
regel om een titel te geven voor ons kleine rapport. We typen het volgende met de (n
) notatie om een teken voor een nieuwe regel in de titelreeks in te voegen:
awk -F: 'BEGIN {print "User Accountsn-------------"} $3 >= 1000 {print $1,$6}' /etc/passwd
= 1000 {print $ 1, $ 6} ‘/ etc / passwd” commando in een terminalvenster.” width=”646″ height=”212″ onload=”pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);” onerror=”this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”>
Patronen zijn volwaardige reguliere expressies en ze zijn er een van de glorie van awk
.
Laten we zeggen dat we de universeel unieke identifiers (UUID’s) van de aangekoppelde bestandssystemen willen zien. Als we zoeken via het /etc/fstab
bestand voor het voorkomen van de tekenreeks “UUID”, zou het die informatie voor ons moeten retourneren.
We gebruiken het zoekpatroon “/ UUID /” in ons commando:
awk '/UUID/ {print $0}' /etc/fstab
Het vindt alle exemplaren van “UUID” en drukt die regels af. We zouden eigenlijk hetzelfde resultaat hebben gekregen zonder de print
actie omdat de standaardactie de hele regel tekst afdrukt. Voor de duidelijkheid is het echter vaak handig om expliciet te zijn. Als je door een script of je geschiedenisbestand kijkt, zul je blij zijn dat je aanwijzingen voor jezelf hebt achtergelaten.
De eerste gevonden regel was een commentaarregel, en hoewel de “UUID” -reeks er middenin staat, awk
nog steeds gevonden. We kunnen de reguliere expressie aanpassen en vertellen awk
om alleen regels te verwerken die beginnen met ‘UUID’. Om dit te doen, typen we het volgende, inclusief het begin van de regel token (^
):
awk '/^UUID/ {print $0}' /etc/fstab
Dat is beter! Nu zien we alleen echte montage-instructies. Om de uitvoer nog verder te verfijnen, typen we het volgende en beperken we de weergave tot het eerste veld:
awk '/^UUID/ {print $1}' /etc/fstab
Als we meerdere bestandssystemen op deze machine hadden aangekoppeld, zouden we een nette tabel met hun UUID’s krijgen.
Ingebouwde functies
awk
heeft veel functies die u kunt aanroepen en gebruiken in uw eigen programma’s, zowel vanaf de opdrachtregel als in scripts. Als je wat gaat graven, zul je het erg vruchtbaar vinden.
Om de algemene techniek voor het aanroepen van een functie te demonstreren, zullen we enkele numerieke bekijken. Het volgende drukt bijvoorbeeld de vierkantswortel van 625 af:
awk 'BEGIN { print sqrt(625)}'
Dit commando drukt de arctangens van 0 (nul) en -1 af (wat toevallig de wiskundige constante is, pi):
awk 'BEGIN {print atan2(0, -1)}'
In de volgende opdracht wijzigen we het resultaat van de atan2()
functie voordat we het afdrukken:
awk 'BEGIN {print atan2(0, -1)*100}'
Functies kunnen uitdrukkingen accepteren als parameters. Hier is bijvoorbeeld een ingewikkelde manier om de vierkantswortel van 25 te vragen:
awk 'BEGIN { print sqrt((2+3)*5)}'
awk scripts
Als uw opdrachtregel ingewikkeld wordt, of als u een routine ontwikkelt waarvan u weet dat u deze opnieuw wilt gebruiken, kunt u uw awk
commando in een script.
In ons voorbeeldscript gaan we al het volgende doen:
- Vertel de shell welk uitvoerbaar bestand moet worden gebruikt om het script uit te voeren.
- Bereiden
awk
om deFS
veldscheidingstekenvariabele om invoertekst te lezen met velden gescheiden door dubbele punten (:
). - Gebruik de
OFS
output veldscheidingsteken om te vertellenawk
dubbele punten gebruiken (:
) om velden in de uitvoer te scheiden. - Zet een teller op 0 (nul).
- Stel het tweede veld van elke regel tekst in op een lege waarde (het is altijd een “x”, dus we hoeven het niet te zien).
- Druk de regel af met het gewijzigde tweede veld.
- Verhoog de teller.
- Druk de waarde van de teller af.
Ons script wordt hieronder weergegeven.
De BEGIN
rule voert de voorbereidende stappen uit, terwijl de END
regel geeft de tellerwaarde weer. De middelste regel (die geen naam of patroon heeft, zodat het overeenkomt met elke regel) wijzigt het tweede veld, drukt de regel af en verhoogt de teller.
De eerste regel van het script vertelt de shell welk uitvoerbaar bestand moet worden gebruikt (awk
, in ons voorbeeld) om het script uit te voeren. Het passeert ook de -f
(bestandsnaam) optie naar awk
, die het laat weten dat de tekst die het gaat verwerken uit een bestand komt. We geven de bestandsnaam door aan het script wanneer we het uitvoeren.
We hebben het onderstaande script als tekst toegevoegd, zodat u kunt knippen en plakken:
#!/usr/bin/awk -f BEGIN { # set the input and output field separators FS=":" OFS=":" # zero the accounts counter accounts=0 } { # set field 2 to nothing $2="" # print the entire line print $0 # count another account accounts++ } END { # print the results print accounts " accounts.n" }
Bewaar dit in een bestand met de naam omit.awk
. Om het script uitvoerbaar te maken, typen we het volgende met chmod
:
chmod +x omit.awk
Nu zullen we het uitvoeren en de /etc/passwd
bestand naar het script. Dit is het bestand awk
zal voor ons verwerken, met behulp van de regels in het script:
./omit.awk /etc/passwd
Het bestand wordt verwerkt en elke regel wordt weergegeven, zoals hieronder weergegeven.
De “x” -vermeldingen in het tweede veld zijn verwijderd, maar merk op dat de veldscheidingstekens nog steeds aanwezig zijn. De regels worden geteld en het totaal wordt onderaan de uitvoer weergegeven.
awk staat niet voor Awkward
awk
staat niet voor onhandig; het staat voor elegantie. Het is beschreven als een verwerkingsfilter en een rapportschrijver. Nauwkeuriger gezegd, het zijn beide, of liever een tool die u voor beide taken kunt gebruiken. In slechts een paar regels, awk
bereikt wat uitgebreide codering in een traditionele taal vereist.
Die kracht wordt benut door het eenvoudige concept van regels die patronen bevatten, die de te verwerken tekst selecteren en acties die de verwerking bepalen.