Inleiding
Linux-hulpprogramma’s volgen vaak de Unix-filosofie van ontwerp. Tools worden aangemoedigd om klein te zijn, platte tekstbestanden te gebruiken voor invoer en uitvoer, en modulair te werken. Vanwege deze erfenis hebben we geweldige functionaliteit voor tekstverwerking met tools zoals sed en awk
.
awk
is zowel een programmeertaal als een tekstverwerker die je kunt gebruiken om tekstgegevens op zeer nuttige manieren te manipuleren. In deze gids zul je ontdekken hoe je de awk
opdrachtregeltool kunt gebruiken en hoe je deze kunt gebruiken om tekst te verwerken.
Basis syntaxis
De awk
opdracht is standaard inbegrepen in alle moderne Linux-systemen, dus je hoeft het niet te installeren om ermee te beginnen.
awk
is het meest nuttig bij het omgaan met tekstbestanden die op een voorspelbare manier zijn opgemaakt. Het is bijvoorbeeld uitstekend in het parseren en manipuleren van tabulaire gegevens. Het werkt op regel-voor-regelbasis en doorloopt het hele bestand.
Standaard gebruikt het witruimte (spaties, tabs, enz.) om velden te scheiden. Gelukkig gebruiken veel configuratiebestanden op je Linux-systeem dit formaat.
De basisindeling van een awk
-opdracht is:
Je kunt ofwel het zoekgedeelte of het actiegedeelte weglaten uit elke awk
-opdracht. Standaard wordt de actie uitgevoerd als het “actie” gedeelte niet is opgegeven, is “print”. Dit drukt eenvoudig alle regels af die overeenkomen.
Als het zoekgedeelte niet is opgegeven, voert awk
de vermelde actie uit op elke regel.
Als beide zijn opgegeven, gebruikt awk
het zoekgedeelte om te beslissen of de huidige regel overeenkomt met het patroon, en voert vervolgens de acties uit bij overeenkomsten.
In zijn eenvoudigste vorm kun je awk
gebruiken zoals cat
om alle regels van een tekstbestand op het scherm af te drukken.
Maak een bestand favorite_food.txt
waarin de favoriete voedingsmiddelen van een groep vrienden worden vermeld:
Gebruik nu de awk
-opdracht om het bestand naar het scherm af te drukken:
Je ziet dat het bestand naar het scherm wordt afgedrukt:
Outputcarrot sandy
wasabi luke
sandwich brian
salad ryan
spaghetti jessica
Dit is niet erg nuttig. Laten we de zoekfiltermogelijkheden van awk
uitproberen door door het bestand te zoeken naar de tekst “zand”:
Outputcarrot sandy
sandwich brian
Zoals je kunt zien, drukt awk
nu alleen de regels af die de tekens “zand” bevatten.
Met reguliere expressies kun je specifieke delen van de tekst targeten. Om alleen de regel weer te geven die begint met de letters “zand”, gebruik je de reguliere expressie ^zand
:
Deze keer wordt slechts één regel weergegeven:
Outputsandwich brian
Vergelijkbaar, je kunt het actieg gedeelte gebruiken om aan te geven welke informatie je wilt afdrukken. Bijvoorbeeld, om alleen de eerste kolom af te drukken, gebruik je de volgende opdracht:
Outputsandwich
U kunt elke kolom (zoals aangegeven door witruimte-delimiters) verwijzen met variabelen die zijn geassocieerd met hun kolomnummer. Bijvoorbeeld, de eerste kolom is $1
, de tweede is $2
, en u kunt de hele regel refereren met $0
.
Interne Variabelen en Uitgebreid Formaat
De awk
-opdracht gebruikt enkele interne variabelen om bepaalde stukken informatie toe te wijzen terwijl het een bestand verwerkt.
De interne variabelen die awk
gebruikt zijn:
- FILENAME: Verwijst naar het huidige invoerbestand.
- FNR: Verwijst naar het nummer van het huidige record ten opzichte van het huidige invoerbestand. Bijvoorbeeld, als u twee invoerbestanden heeft, zou dit u het recordnummer van elk bestand vertellen in plaats van als totaal.
- FS: De huidige veldscheider die wordt gebruikt om elk veld in een record aan te duiden. Standaard is dit ingesteld op witruimte.
- NF: Het aantal velden in het huidige record.
- NR: Het nummer van het huidige record.
- OFS: De veldscheider voor de uitvoergegevens. Standaard is dit ingesteld op witruimte.
- ORS: De recordscheider voor de uitvoergegevens. Standaard is dit een nieuwregelkarakter.
- RS: Het recordseparator wordt gebruikt om afzonderlijke records in het invoerbestand te onderscheiden. Standaard is dit een newline-teken.
U kunt de waarden van deze variabelen naar wens wijzigen om aan de behoeften van uw bestanden te voldoen. Meestal doet u dit tijdens de initialisatiefase van uw verwerking.
Dit brengt ons bij een ander belangrijk concept. De syntaxis van awk
is iets complexer dan wat je tot nu toe hebt gebruikt. Er zijn ook optionele BEGIN
en END
blokken die commando’s kunnen bevatten om respectievelijk vóór en na de bestandsverwerking uit te voeren.
Dit maakt onze uitgebreide syntaxis er ongeveer zo uit:
De BEGIN
en END
trefwoorden zijn specifieke reeksen voorwaarden, net als de zoekparameters. Ze komen overeen vóór en na het verwerken van het document.
Dit betekent dat u sommige interne variabelen in de BEGIN
-sectie kunt wijzigen. Bijvoorbeeld, het bestand /etc/passwd
is gescheiden door dubbelepunten (:
) in plaats van spaties.
Om de eerste kolom van dit bestand af te drukken, voert u het volgende commando uit:
Outputroot
daemon
bin
sys
sync
games
man
. . .
U kunt de BEGIN
en END
blokken gebruiken om informatie over de velden die u afdrukt weer te geven. Gebruik het volgende commando om de gegevens uit het bestand om te zetten in een tabel, mooi opgemaakt met tabs met behulp van \t
:
U ziet deze uitvoer:
OutputUser UID GID Home Shell
--------------
root 0 0 /root /bin/bash
daemon 1 1 /usr/sbin /bin/sh
bin 2 2 /bin /bin/sh
sys 3 3 /dev /bin/sh
sync 4 65534 /bin /bin/sync
. . .
---------
File Complete
Zoals u kunt zien, kunt u dingen behoorlijk mooi formatteren door gebruik te maken van enkele functies van awk
.
Elk van de uitgebreide secties is optioneel. Sterker nog, de hoofdactiesectie zelf is optioneel als er een andere sectie is gedefinieerd. Je kunt bijvoorbeeld dingen doen zoals dit:
En je ziet deze output:
OutputWe can use awk like the echo command
Nu gaan we kijken hoe je tekst kunt zoeken binnen velden van de uitvoer.
Veldzoeken en samengestelde expressies
In een van de vorige voorbeelden heb je de regel in het bestand favorite_food.txt
afgedrukt die begon met “sand”. Dit was gemakkelijk omdat je zocht naar het begin van de hele regel.
Wat als je wilt weten of een zoekpatroon overeenkomt met het begin van een veld in plaats daarvan?
Maak een nieuwe versie van het bestand favorite_food.txt
waarin voor elk voedsel van een persoon een itemnummer wordt toegevoegd:
Als je alle voedingsmiddelen uit dit bestand wilt vinden die beginnen met “sa”, zou je iets als dit kunnen proberen:
Dit toont alle regels die “sa” bevatten:
Output1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan
Hierbij match je elke instantie van “sa” in het woord. Dit omvat uiteindelijk dingen zoals “wasabi” die het patroon in het midden hebben, of “sandy” die niet in de kolom staat die je wilt. In dit geval ben je alleen geïnteresseerd in woorden die beginnen met “sa” in de tweede kolom.
U kunt awk
vertellen om alleen overeenkomsten te vinden aan het begin van de tweede kolom met behulp van deze opdracht:
Zoals u kunt zien, stelt dit ons in staat om alleen te zoeken aan het begin van de tweede kolom voor een overeenkomst.
Het gedeelte field_num ~
geeft aan dat awk
alleen aandacht moet besteden aan de tweede kolom.
Output3 sandwich brian
4 salad ryan
U kunt net zo gemakkelijk zoeken naar dingen die niet overeenkomen door het “!” teken voor de tilde (~) op te nemen. Met deze opdracht worden alle regels geretourneerd die geen voedsel hebben dat begint met “sa”:
Output1 carrot sandy
2 wasabi luke
5 spaghetti jessica
Als u later besluit dat u alleen geïnteresseerd bent in regels die niet beginnen met “sa” en het itemnummer minder dan 5 is, kunt u een samengestelde expressie als deze gebruiken:
Dit introduceert een paar nieuwe concepten. Het eerste is de mogelijkheid om extra vereisten toe te voegen voor de overeenkomst van de regel door de &&
operator te gebruiken. Hiermee kunt u een willekeurig aantal voorwaarden combineren voor de overeenkomst van de regel. In dit geval gebruikt u deze operator om een controle toe te voegen dat de waarde van de eerste kolom minder is dan 5.
U zult deze uitvoer zien:
Output1 carrot sandy
2 wasabi luke
U kunt awk
gebruiken om bestanden te verwerken, maar u kunt ook werken met de uitvoer van andere programma’s.
Verwerken van uitvoer van andere programma’s
U kunt het awk
commando gebruiken om de uitvoer van andere programma’s te analyseren in plaats van een bestandsnaam op te geven. Bijvoorbeeld, u kunt awk
gebruiken om het IPv4-adres uit het ip
commando te halen.
Het ip a
commando geeft het IP-adres, broadcastadres en andere informatie weer over alle netwerkinterfaces op uw machine. Om de informatie voor de interface genaamd eth0
weer te geven, gebruikt u dit commando:
U ziet de volgende resultaten:
Output2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
U kunt awk
gebruiken om de inet
regel te targeten en vervolgens alleen het IP-adres af te drukken:
De -F
vlag vertelt awk
om te delen door voorwaartse slashes of spaties met de reguliere expressie [\/ ]+
. Dit splitst de regel inet 172.17.0.11/16
in afzonderlijke velden. Het IP-adres bevindt zich in het derde veld omdat de spaties aan het begin van de regel ook tellen als een veld, aangezien u hebt gedeeld door spaties en slashes. Merk op dat awk
opeenvolgende spaties als één spatie behandelde in dit geval.
De uitvoer toont het IP-adres:
Output172.17.0.11
U zult veel plaatsen vinden waar u awk
kunt gebruiken om te zoeken of de uitvoer van andere commando’s te analyseren.
Conclusie
Tegenwoordig zou je een basisbegrip moeten hebben van hoe je het awk
-commando kunt gebruiken om tekstbestanden en tekststreams te manipuleren, formatteren en selectief af te drukken. Awk is echter een veel groter onderwerp en is eigenlijk een volledige programmeertaal met variabelentoewijzing, controlestructuren, ingebouwde functies en meer. Je kunt het binnen je eigen scripts gebruiken om tekst op een betrouwbare manier te formatteren.
Om meer te leren over awk
, kun je het gratis publiek domein boek van de makers lezen, dat veel meer gedetailleerd ingaat.