awkAan de slag met awk


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

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:
  1. BEGIN ... en END ... zijn optioneel en worden uitgevoerd voor of na het verwerken van awk-invoerregels.
  2. Voor elke regel in de awk-invoer, als voorwaarde <condN> vlees is, wordt het bijbehorende blok <program actions> uitgevoerd.
  3. {<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 als FS .
  • 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
 

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.