awk Zelfstudie
Aan de slag met awk
Zoeken…
Opmerkingen
De naam AWK komt van de laatste initialen van de makers Alfred V. Aho, Peter J. Weinberger, en
Brian W. Kernighan.
Middelen
versies
| Naam | Eerste versie | Versie | Publicatiedatum |
|---|---|---|---|
| POSIX awk | 1992 | IEEE Std 1003.1, 2013-editie | 2013/04/19 |
| Eén True Awk of nawk of BWK awk | 198x | - | 2012/12/20 |
| GNU awk of gawk | 1986 | 4.1.3 | 2015/05/19 |
Hallo Wereld
Het voorbeeld van Hello world is zo simpel als:
awk 'BEGIN {print "Hello world"}'
Het meest eenvoudige awk programma bestaat uit een echte waarde (meestal 1 ) en geeft awk zijn input:
$ date | awk '1'
Mon Jul 25 11:12:05 CEST 2016
Omdat "hallo wereld" ook een echte waarde is, zou je ook kunnen zeggen:
$ date | awk '"hello world"'
Mon Jul 25 11:12:05 CEST 2016
Je intentie wordt echter veel duidelijker als je schrijft
$ date | awk '{print}'
Mon Jul 25 11:12:05 CEST 2016
in plaats daarvan.
Hoe AWK-programma's uit te voeren
Als het programma kort is, kunt u het opnemen in de opdracht die awk uitvoert:
awk -F: '{print $1, $2}' /etc/passwd
In dit voorbeeld gebruiken we opdrachtregel- -F: we adviseren awk om te gebruiken: als scheidingsteken voor invoervelden. Het is hetzelfde als
awk 'BEGIN{FS=":"}{print $1,$2}' file
Als alternatief kunnen we de hele awk-code opslaan in een awk-bestand en dit awk-programma als volgt noemen:
awk -f 'program.awk' input-file1 input-file2 ...
program.awk kan elk multiline-programma zijn, dwz:
# file print_fields.awk
BEGIN {print "this is a header"; FS=":"}
{print $1, $2}
END {print "that was it"}
En voer het vervolgens uit met:
awk -f print_fields.awk /etc/passwd #-f advises awk which program file to load
Of meer in het algemeen:
awk -f program-file input-file1 input-file2 ...
Het voordeel van het hebben van het programma in een apart bestand is dat u het programma met de juiste identificatie kunt schrijven om logisch te zijn, u kunt opmerkingen toevoegen met #, enz.
AWK door voorbeelden
AWK is een taal voor stringmanipulatie, die grotendeels wordt gebruikt in UNIX-systemen. Het idee achter AWK was om een veelzijdige taal te maken om te gebruiken bij het werken aan bestanden, die niet te ingewikkeld was om te begrijpen.
AWK heeft enkele andere varianten, maar het hoofdconcept is hetzelfde, alleen met extra functies. Deze andere varianten zijn NAWK en GAWK. GAWK bevat alle functies van beide, terwijl NAWK een stap boven AWK staat, als je wilt.
De meest eenvoudige manier om aan AWK te denken, is te overwegen dat het uit 2 hoofdonderdelen bestaat. Het patroon en de actie.
Waarschijnlijk het meest eenvoudige voorbeeld van AWK: (Zie ook: Hallo wereld)
BEGIN {print "START"}
{print }
END {print "STOP" }
Hier zijn de sleutelwoorden BEGIN en END het patroon, terwijl de actie zich binnen de {} bevindt. Dit voorbeeld zou nutteloos zijn, maar er zijn slechts kleine wijzigingen nodig om dit tot een nuttige functie te maken.
BEGIN {print "File\tAuthor"}
{print $8, "\t", $3}
END {print " - DONE - "}
Hier staat \t voor een Tab-teken en wordt het gebruikt om de grenzen van de uitvoerregels te verhogen. $ 8 en $ 3 zijn vergelijkbaar met het gebruik dat wordt gezien in Shell Scripts , maar in plaats van de 3e en 8e argumenten te gebruiken, gebruikt het de 3e en 8e kolom van de invoerregel.
Dit voorbeeld zou dus afdrukken: Bestandsauteur op de bovenste regel, terwijl de tweede regel te maken heeft met de bestandspaden. $ 8 is de naam van het bestand, $ 3 is de eigenaar (bij het bekijken van het mappad zal dit duidelijker zijn). Eindelijk zou de onderste regel worden afgedrukt, zoals je zou verwachten - GEREED -
Creditering voor het bovenstaande voorbeeld gaat naar http://www.grymoire.com/Unix/Awk.html
Referentiebestand
coins.txt van Greg Goebel:
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
silver 10 1981 USA ingot
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
silver 1 1986 USA Liberty dollar
gold 0.25 1986 USA Liberty 5-dollar piece
silver 0.5 1986 USA Liberty 50-cent piece
silver 1 1987 USA Constitution dollar
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple Leaf
Minimale theorie
Algemene awk one-liner:
awk <awk program> <file>
of:
<shell-command> | awk <awk program>
<shell-command> en <file> worden geadresseerd als awk-invoer .
<awk program> is een code volgens deze sjabloon (enkele, niet dubbele, aanhalingstekens):
'BEGIN {<init actions>};
<cond1> {<program actions>};
<cond2> {<program actions>};
...
END {<final actions>}'
waar:
-
<condX>voorwaarde is meestal een reguliere expressie/re/, te matchen met awk invoerregels; -
<* actions>zijn opeenvolgingen van instructies , vergelijkbaar met shell-opdrachten, uitgerust met C-achtige constructies.
`` wordt verwerkt volgens de volgende regels:
-
BEGIN ...enEND ...zijn optioneel en worden uitgevoerd voor of na het verwerken van awk-invoerregels. - Voor elke regel in de awk-invoer, als voorwaarde
<condN>vlees is, wordt het bijbehorende blok<program actions>uitgevoerd. -
{<program actions>}standaard ingesteld op{print $0}.
Voorwaarden kunnen worden gecombineerd met standaard logische operatoren:
/gold/ || /USA/ && !/1986/
waar && voorrang heeft op || ;
Het print statement . print item1 item2 statement print items op STDOUT.
Items kunnen variabelen ( X , $0 ), tekenreeksen ("hallo") of getallen zijn.
item1, item2 worden verzameld met de waarde van de OFS variabele;
item1 item2 zijn justapoxed ! Gebruik item1 " " item2 voor spaties of printf voor meer functies.
Variabelen hebben geen $ nodig, dwz: print myVar;
De volgende speciale variabelen zijn ingebouwd in awk:
-
FS: fungeert als veldscheider om awk-invoerregels in velden te splitsen. Ik kan een enkel karakter zijn,FS="c"; een nulstring,FS=""(dan wordt elk afzonderlijk karakter een afzonderlijk veld); een reguliere expressie zonder schuine strepen,FS="re";FS=" "staat voor reeksen spaties en tabbladen en is de standaardwaarde. -
NF: het aantal te lezen velden; -
$1,$2, ...: 1e veld, 2e veld. enz. van de huidige invoerregel, -
$0: huidige invoerregel; -
NR: huidig putregelnummer. -
OFS: tekenreeks om velden te sorteren bij het afdrukken. -
ORS: uitvoer recordscheider, standaard een nieuwe regel. -
RS: scheidingsteken voor invoerregel (record). Standaard ingesteld op nieuwe regel. Instellen alsFS. -
IGNORECASE: beïnvloedt FS en RS wanneer zijn reguliere expressie;
Voorbeelden
Filter lijnen op regexp gold en tel ze:
# awk 'BEGIN {print "Coins"} /gold/{i++; print $0} END {print i " lines out of " NR}' coins.txt
Coins
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
gold 0.25 1986 USA Liberty 5-dollar piece
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple Leaf
9 lines out of 13
Standaard print $0 actie en conditie gebaseerd op interne awk variabele NR :
# awk 'BEGIN {print "First 3 coins"} NR<4' coins.txt
First 3 coins
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
silver 10 1981 USA ingot
Formatteren met C-stijl `printf`: # awk '{printf ("%s \t %3.2f\n", $1, $2)}' coins.txt
gold 1.00
gold 1.00
silver 10.00
gold 1.00
gold 1.00
gold 0.50
gold 0.10
silver 1.00
gold 0.25
silver 0.50
silver 1.00
gold 0.25
gold 1.00
Conditie voorbeelden
awk 'NR % 6' # prints all lines except those divisible by 6
awk 'NR > 5' # prints from line 6 onwards (like tail -n +6, or sed '1,5d')
awk '$2 == "foo"' # prints lines where the second field is "foo"
awk '$2 ~ /re/' # prints lines where the 2nd field mateches the regex /re/
awk 'NF >= 6' # prints lines with 6 or more fields
awk '/foo/ && !/bar/' # prints lines that match /foo/ but not /bar/
awk '/foo/ || /bar/' # prints lines that match /foo/ or /bar/ (like grep -e 'foo' -e 'bar')
awk '/foo/,/bar/' # prints from line matching /foo/ to line matching /bar/, inclusive
awk 'NF' # prints only nonempty lines (or: removes empty lines, where NF==0)
awk 'NF--' # removes last field and prints the line
Door een actie {...} toe te voegen, kan een specifiek veld worden afgedrukt in plaats van de hele regel, bijvoorbeeld:
awk '$2 ~ /re/{print $3 " " $4}'
drukt het derde en vierde veld van lijnen af waar het tweede veld de regex / re / combineert.
Enkele stringfuncties
substr() :
# awk '{print substr($3,3) " " substr($4,1,3)}'
86 USA
08 Aus
81 USA
84 Swi
79 RSA
81 RSA
86 PRC
86 USA
86 USA
86 USA
87 USA
87 USA
88 Can
match(s, r [, arr]) retourneert de positie in s waar de regex r voorkomt en stelt de waarden van RSTART en RLENGTH . Als het argument arr wordt opgegeven, wordt de array arr geretourneerd waar elementen zijn ingesteld op de overeenkomende haakjes-subexpressie. De 0'-elementovereenkomsten van arr worden ingesteld op de volledige regex-overeenkomst. Expressies arr[n, "start"] en arr[n, "length"] geven ook de startpositie en lengte van elke overeenkomende substring.
Meer stringfuncties:
sub(/regexp/, "newstring"[, target])
gsub(/regexp/, "newstring"[, target])
toupper("string")
tolower("string")
verklaringen
Een eenvoudige verklaring is vaak een van de volgende:
variable = expression
print [ expression-list ]
printf format [ , expression-list ]
next # skip remaining patterns on this input line
exit # skip the rest of the input
Als stat1 en stat2 verklaringen zijn, zijn de volgende ook verklaringen:
{stat}
{stat1; stat2}
{stat1
stat2}
if ( conditional ) statement [ else statement ]
De volgende standaard C-achtige constructen zijn statements:
if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
break # usual C meaning
continue # usual C meaning
Een lus in C-stijl om het beschrijvingselement met variabele lengte af te drukken, beginnend met veld 4:
# awk '{out=""; for(i=4;i<=NF;i++){out=out" "$i}; print out}' coins.txt
USA American Eagle
Austria-Hungary Franz Josef 100 Korona
USA ingot
Switzerland ingot
RSA Krugerrand
RSA Krugerrand
PRC Panda
USA Liberty dollar
USA Liberty 5-dollar piece
USA Liberty 50-cent piece
USA Constitution dollar
USA Constitution 5-dollar piece
Canada Maple Leaf
Merk op dat i is geïnitialiseerd op 0.
Als voorwaarden en berekeningen van toepassing zijn op niet-magnetische velden:
# awk '/gold/ {if($3<1980) print $0 "$" 425*$2}' coins.txt
gold 1 1908 Austria-Hungary Franz Josef 100 Korona $425
gold 1 1979 RSA Krugerrand $425
AWK uitvoerbaar script
#!/usr/bin/gawk -f
# This is a comment
(pattern) {action}
...
Shell-variabelen doorgeven
# var="hello"
# awk -v x="$var" 'BEGIN {print x}'
hello