awk
Aho & Weinberger & Kernighan

Lukáš Bařinka

awk
pattern scanning and processing language


man -f awk

TOC

Obsah

  1. Syntax
  2. Basic usage
  3. Control Statements
  4. Arrays
  5. Input/Output
  6. Functions
  7. Array Traversal
  1. Syntaxe
  2. Jednoduché použití
  3. Řídící konstrukce
  4. Pole
  5. Vstup a výstup
  6. Funkce
  7. Průchod polem

SyntaxSyntaxe

ImplementationsImplmentace

awk
Old (original) implementation now, usualy link to nawk/mawk/gawk
nawk
New-awk implementation (+ arrays and functions)
gawk
GNU Project's implementation
mawk
New-awk reimplementation with extensions using bytecode (faster)
awk
Původní implementace dnes obvykle link na nawk/mawk/gawk
nawk
New-awk implementace (+ pole a funkce)
gawk
GNU implementace
mawk
New-awk reimplementace s bytecode rozšířeními (rychlejší)

Syntax overviewPřehled syntaxe

awk [ POSIX or GNU style options ] -f program-file [ -- ] file ...

awk [ POSIX or GNU style options ] [ -- ] program-text file ...

AWK start

Script syntaxSyntaxe skriptu

Script syntax

PreprocessingPředzpracování

I/O Preprocessing

Basic usageJednoduché použití

OptionsPřepínače

-F EREset Field Separator using ERE
-v var=valset value val into variable varbefore BEGIN section
-F EREnastaví Field Separator na ERE
-v var=valnastaví prom. var na hodnotu valpřed sekcí BEGIN

							awk 'BEGIN { FS = ":" }; { print $1 }' /etc/passwd
							awk -F: '{ print $1 }' /etc/passwd
							awk -v FS=: '{ print $1 }' /etc/passwd
							awk '{ print $1 }' FS=: /etc/passwd
						

ActionsAkce

print expr
Print expression expr or the current record (default)
exit expr
Exit AWK script with expr exit code
num = sub( ERE, subst [, text] )
num = gsub( ERE, subst [, text] )
string = gensub( ERE, subst, flags [, text] )
Substitute ERE with subst in text (default: $0)
print expr
Vypíše výraz expr nebo celý záznam (výchozí)
exit expr
Ukončí AWK skript s návratovým kódem expr
num = sub( ERE, subst [, text] )
num = gsub( ERE, subst [, text] )
string = gensub( ERE, subst, flags [, text] )
Nahradí ERE textem subst ve vstupu text (výchozí: $0)

ValuesHodnoty

var Variable (value of variable) Inital (uninitialized variable) value: (int) 0, (string) ""
"val" String value e.g. "foo"
number Numeric value e.g. 123.45
/ERE/ Extended Regular Expression
$expr Value of exprth filed e.g. $NF — the last field, $(NF-1) — the last but one
var Proměnná (hodnota proměnné) Výchozí (neinicializovaná proměnná) hodnota: (int) 0, (string) ""
"val" Řetězcová hodnota např. "foo"
číslo Číselná hodnota např. 123.45
/ERE/ Rozšířený regulární výraz
$expr Hodnota expr. pole e.g. $NF — poslední pole, $(NF-1) — předposlední pole

Control StatementsŘídící konstrukce

StatementsKonstrukce

  • if (condition) statement [ else statement ]
  • while (condition) statement
  • do statement while (condition)
  • for (expr1; expr2; expr3) statement
  • for (var in array) statement
  • break
  • continue
  • delete array[index]
  • delete array
  • exit [ expression ]
  • { statements }

Fields walkthroughtPrůchod záznamem


							awk -F: '{ for(i=1;i<=NF;i++) print i,$i; print "-----" }' /etc/passwd
						

							awk -f - /etc/passwd <<'AWK'
							BEGIN {
							  FS = ":"
							}
							{
							  print "Record:", NR
							  for (i=1; i<=NF; i++) {
							    if ( i == 2 ) continue
							    if ( $i != "" ) print i, $i
							    else print i, "-none-"
							  }
							  print "-----"
							}
							AWK
						

							Record: 1
							1 root
							3 0
							4 0
							5 root
							6 /root
							7 /bin/bash
							-----
							...
							-----
							Record: 47
							1 debian-spamd
							3 124
							4 132
							5 -none-
							6 /var/lib/spamassassin
							7 /usr/sbin/nologin
							-----
						

Exit


							awk -F: '
							  NF != 7         { print "NF"; e=1; exit 3 }
							  $2 != "x"       { print "x"; e=1; exit 4 }
							  $3 !~ /^[0-9]+/ { print "uid"; e=1; exit 5 }
							  $4 !~ /^[0-9]+/ { print "gid"; e=1; exit 6 }
							  END             {
							                    if ( e ) exit
							                    if ( NR==0 ) { print "empty"; exit 1 }
							                    else { print "ok"; exit 0 }
							                  }
							' /etc/passwd; echo $?
						

ArraysPole

Syntax of arraySyntaxe pole

  • Assignment: arr[index] = value
  • Usualy initialized using split function item_count = split("one two three", arr, " ")
  • Multi-dimensional array using , character Translated to SUBSEP=\034 [ASCII file separator] e.g. x=5; y=7; arr[x,y] is stored as arr["5\0347"]
  • All arrays are associative indexed by a string value
  • Přiřazení: arr[index] = value
  • Obvykle neinicializované pomocí funkce split item_count = split("one two three", arr, " ")
  • Vícerozměrné pole používá znak , Překládá na SUBSEP=\034 [ASCII file separator] např. x=5; y=7; arr[x,y] je uloženo jako arr["5\0347"]
  • Všechna pole jsou asociativní indexována řetězcem

Array walkthroughtPrůchod polem

  • Array elements iteration general = string indices
    
    									for ( index in arr ) print index " -> " arr[index]
    								
  • Array elements iteration indexed = numeric indices
    
    									item_count = split("one two three", arr, " ")
    									for ( i=1; i<=item_count; i++ ) print i, arr[i]
    								
  • Array element test
    
    									if ( index in arr ) print arr[index]
    								
  • Iterace přes prvky obecná = řetězcové indexy
    
    									for ( index in arr ) print index " -> " arr[index]
    								
  • Iterace přes prvky indexovaná = číselné indexy
    
    									item_count = split("one two three", arr, " ")
    									for ( i=1; i<=item_count; i++ ) print i, arr[i]
    								
  • Test přítomnosti prvku v poli (indexu)
    
    									if ( index in arr ) print arr[index]
    								

Multidimensional arrayVícerozměrné pole

  • GNU awk supports true multidimensional arrays
  • GNU awk podporuje skutečné vícerozměrné pole

							a[1] = 5
							a[2][1] = 6
						

Store and recall valuesUložení a výpis hodnot


							history \
							| awk '{ print $2 }' \
							| sort \
							| uniq -c \
							| sort -rn \
							| head
						

							history \
							| awk '
							      { a[$2]++ }
							  END {
							        PROCINFO["sorted_in"]="@val_num_desc"
							        for( i in a ) {
							          print a[i] " " i
							          if (++c == 10) exit
							        }
							      }
							'
						

Randomize arrayPřeskládání pole


							    { file[NR] = $0 }
							END {
							      srand()
							      for ( i=1; i<=NR; i++ ) {
							        RAND = int(NR*rand())+1
							        temp = file[i]
							        file[i] = file[RAND]
							        file[RAND] = temp
							      }
							      for ( i=1; i<=NR; i++ ) {
							        print "\"" file[i] "\""
							        # system( system( cmd " " X ) )
							      }
							    }
						
!x[$0]++

Input/OutputVstup a výstup

Flush and closeVyprázdnění a uzavření

fflush( [file] )
Flush any buffers associated with the open output Default: all
close( file [, how] )
Close file, pipe, co-process How: to | from
fflush( [soubor] )
Vyprázdnění bufferů asociovaných s otevřeným výstupem Výchozí: všechny
close( soubor [, jak] )
Uzavření souboru, roury nebo co-procesu Jak: to | from

InputVstup

  • getline
  • getline <file
  • getline var
  • getline var <file
  • command | getline [var]
  • command |& getline [var]
  • next
  • nextfile

OutputVýstup

  • print
  • print expr-list
  • print expr-list >file
  • printf fmt, expr-list
  • printf fmt, expr-list >file

Additional output redirectionDalší přesměrování výstupu

print ... >> file
Append output to file
print ... | command
Write on pipe
print ... |& command
Send data to coprocess or socket
print ... >> soubor
Přidat výstup na konec souboru
print ... | příkaz
Zápis do roury (na vstup příkazu)
print ... |& příkaz
Poslání dat do ko-procesu nebo socketu

Speciální soubory (síťová komunikace)

Command executionSpouštění příkazů

system( cmd-line )
Execute cmd-line, and return exit status

TCP communicationTCP komunikace


							#!/usr/bin/awk -f
							BEGIN {
								   server="wordnetweb.princeton.edu"

								   # define HTTP connection to web server
								   connection="/inet/tcp/0/"server"/www"

								   # construct HTTP request line
								   term=ARGV[1]
								   url="/perl/webwn?s=" term
								   request="GET " url " HTTP/1.0\n\n"
								   start=0

								   # send HTTP request
								   print "Sending request..." > "/dev/stderr"
								   print request |& connection

								   # receive HTTP response
								   print "Receiving response..." > "/dev/stderr"
								   while (connection |& getline) {
								     ... # data processing
								   }

								   close(connection)
							}
						

Data processingZpracování dat


							# debug to stderr
							print ++lines,go "::" $0 >> "/dev/stderr"

							# process data
							if ( $0 ~ "<h3>" ) {
							   go=1
							   gsub("^.*<h3>","")
							   gsub("<[^>]*>","")
							   print
							   continue
							}

							if ( go && $0 ~ "<li>" ) {
							   gsub("<i>[:space:]*</i>","")
							   gsub("<i>","\n > ")
							   gsub("<[^>]*>","")
							   sub("S: \\(.\\) ","")
							   gsub(";","\n >")
							   print " * " $0
							}

							if ( $0 ~ "</ul>" ) {
							   go=0
							   continue
						 	}
						

FunctionsFunkce

Built-in functionsVestavěné funkce

Numeric functionsNumerické funkce
exp(expr), int(expr), log(expr), rand(), sin(expr), sqrt(expr), srand([expr]), …
String functionsŘetězcové funkce
num = asort(src [, dst [, how]]), num = asorti(src [, dst [, how]]), num = index(str,text), num = length([str]), str = gensub(restrhow [, text]), num = sub(restr [, text]), num = gsub(restr [, text]), num = match(strre [, arr]), num = split(strarr [, re]), str = sprintf(fmt,expr-list), num = strtonum(str), str = substr(strfrom [, len]), …

Built-in functionsVestavěné funkce

Time functionsČasové funkce
tstamp = mktime(datespec), tstamp = systime(), str = strftime([format [, timestamp [, utc-flag]]])
Bit Manipulations functionsBitové funkce
and(v1v2, [, …]), compl(val), x/or(v1v2, [, …]), r/lshift(valcount)
Type functionsTypové funkce
isarray(x), typeof(x)
Internationalization functions„Internacionalizační“ funkce
bindtextdomain(directory [, domain]), dcgettext(string [, domain [, category]]), dcngettext(string1string2number [, domain [, category]])

User functionsUživatelské funkce

function name(parameter list) { statements }

  • Arrays are passed by reference,
    other variables are passed by value
  • Local variables are declared as extra parameters in parameter list (separated by extra spaces) function f(p, q    , a, b) # a and b are local
  • Functions may call each other and may be recursive
  • Function is called by name and followed directly with (parameter list) e.g. f(1, 2)
  • Return value is set using return expr
  • Parametry se předávají hodnotou,
    pole se předávají odkazem
  • Lokální proměnné se definují v seznamu parametrů (jsou odděleny mezerami) function f(p, q    , a, b) # a, b jsou lokální
  • Funkce mohou být rekurzivní
  • Funkce se volá bez mezer mezi názvem funkce a závorkami např. f(1, 2)
  • Návratová hodnota fukce: return expr

User-defined function example (sources)Ukázka uživatelských funkcí (zdroje)

Generate software list (sources)

User-defined function example (results)Ukázka uživatelských funkcí (výstupy)

Generate software list (results)
Data 1
/var/db/pkg

							app-admin      app-shells  dev-python    net-dns       sys-apps    sys-power
							app-arch       app-text    dev-util      net-firewall  sys-auth    sys-process
							app-backup     app-vim     dev-vcs       net-fs        sys-block   virtual
							app-editors    dev-db      mail-client   net-libs      sys-boot    www-servers
							app-emulation  dev-java    mail-mta      net-mail      sys-devel   x11-libs
							app-i18n       dev-lang    media-fonts   net-misc      sys-fs      x11-misc
							app-misc       dev-libs    media-libs    net-nds       sys-kernel  x11-proto
							app-portage    dev-perl    net-analyzer  perl-core     sys-libs
						
/var/db/pkg/app-misc

							ca-certificates-20110502-r1
							editor-wrapper-4
							mc-4.8.1-r1
							BUILD_TIME  CXXFLAGS         HOMEPAGE            NEEDED        SIZE
							CATEGORY    DEFINED_PHASES   INHERITED           NEEDED.ELF.2  SLOT
							CBUILD      DEPEND           IUSE                PF            USE
							CFLAGS      DESCRIPTION      KEYWORDS            PKGUSE
							CHOST       EAPI             LDFLAGS             RDEPEND
							CONTENTS    environment.bz2  LICENSE             repository
							COUNTER     FEATURES         mc-4.8.1-r1.ebuild  REQUIRED_USE
							mime-types-8
							pax-utils-0.2.3
							realpath-1.15-r1
							screen-4.0.3-r4
						
Data 2
/var/db/pkg/app-misc/mc-4.8.1-r1/DESCRIPTION

							GNU Midnight Commander is a text based file manager
						
/var/db/pkg/app-misc/mc-4.8.1-r1/HOMEPAGE

							http://www.midnight-commander.org
						
ScriptSkript

							#!/usr/bin/awk -f

							BEGIN {
							   FS = "/"
							   basedir = "/var/db/pkg"
							   print "===== Software list ====="

							   while ( "cd /var/db/pkg; ls -d */*" | getline ) {
							     if ( $1 != category ) {
							       category = $1
							       print "\n==== " category " ===="
							     }
							     pkg( $2 )
							   }

							   print "\n --- //Generated: " strftime( "%c" ) "//"
							}
						
FunctionFunkce

							function pkg( info ) {
							  package = info
							  sub( "-[0-9].*", "", package )

							  version = info
							  sub( package"-", "", version )

							  desc_file = basedir"/" $0 "/DESCRIPTION"
							  getline description < desc_file
							  close( desc_file )

							  web_file = basedir "/" $0 "/HOMEPAGE"
							  getline homepage < web_file
							  close( web_file )
							  gsub( " ", " \\\\ ", homepage )

							  print "  * **" package "** //(" version ")// \
							    \\\\ " description " \\\\ " homepage
							}
						

Array TraversalPrůchod polem

Default traversalVýchozí průchod


							BEGIN {
							  n = split( "f e d c b a", a, " " )
							  for ( i in a )
							     print i, a[i]
							}

							4 c
							5 b
							6 a
							1 f
							2 e
							3 d
						

Manual traversalManuální průchod


							BEGIN {
							  n = split( "f e d c b a", a, " " )
							  for ( i=1; i<=n; i++ )
							     print i, a[i]
							}

							1 f
							2 e
							3 d
							4 c
							5 b
							6 a
						

Array sort by valueSeřazení pole podle hodnoty


							BEGIN {
							  split( "f e d c b a", a, " " )
							  n = asort( a )
							  for ( i=1; i<=n; i++ )
							    print i, a[i]
							}

							1 a
							2 b
							3 c
							4 d
							5 e
							6 f
						
Array sort by value

Array sort by indexSeřazení pole podle indexu


							BEGIN {
							  a["z"] = 11
							  a["x"] = 99
							  a["y"] = 100
							  n = asorti( a, b )
							  for ( i=1; i<=n; i++ )
							    print i, b[i], a[b[i]]
							}

							1 x 99
							2 y 100
							3 z 11
						
Array sort by index

Defined order of traversalDefinovaný průchod polem

PROCINFO["sorted_in"]
Value controls order in which array elements are traversed in for loops Hodnota ovládá způsob, jakým je pole procházeno ve for cyklu "@ind_str_asc", "@ind_num_asc", "@val_type_asc", "@val_str_asc", "@val_num_asc", "@ind_str_desc", "@ind_num_desc", "@val_type_desc", "@val_str_desc", "@val_num_desc", and "@unsorted" or "cmp_func"
function cmp_func(i1, v1, i2, v2)
Return code depending on how elements of array are to be ordered Návratová hodnota nastavuje způsob řazení prvků v poli

Preset traversal orderPřednastavený způsob průchodu


							BEGIN {
							  a["z"] = 11
							  a["x"] = 99
							  a["y"] = 100
							  PROCINFO["sorted_in"] = "@ind_str_asc"
							  for ( i in a )
							    print i, a[i]
							}

							x 99
							y 100
							z 11
						

Custom traversal orderVlastní způsob průchodu


							function f(a, b, c, d) {
							  r = rand() - 0.5
							  print "?", a, b, c, d, r
							  return r
							}

							BEGIN {
							  srand()
							  a["z"]=11; a["x"]=99; a["y"]=100
							  PROCINFO["sorted_in"] = "f"
							  for ( i in a )
							    print i, a[i]
							}
						

							? y 100 z 11 0.439477
							? x 99 z 11 -0.176757
							x 99
							z 11
							y 100
						

Array usage exampleUkázka použití pole


							<section id="toc">
							  <h2>
							    <span lang="en">TOC</span>
							    <span lang="cs">Obsah</span>
							  </h2>
							  <ol lang="en">
							    <li><a href="#syntax">Syntax</a></li>
							    <li><a href="#basic">Basic usage</a></li>
							    <li><a href="#control">Control Statements</a></li>
							    <li><a href="#arrays">Arrays</a></li>
							    <li><a href="#i-o">Input/Output</a></li>
							    <li><a href="#functions">Functions</a></li>
							    <li><a href="#traversal">Array Traversal</a></li>
							  </ol>
							  <ol lang="cs">
							    <li><a href="#syntax">Syntaxe</a></li>
							    <li><a href="#basic">Jednoduché použití</a></li>
							    <li><a href="#control">Řídící konstrukce</a></li>
							    <li><a href="#arrays">Pole</a></li>
							    <li><a href="#i-o">Vstup a výstup</a></li>
							    <li><a href="#functions">Funkce</a></li>
							    <li><a href="#traversal">Průchod polem</a></li>
							  </ol>
							</section>
						

							<section>
							  <section id="syntax">
							    <h2>
							      <span lang="en">Syntax</span>
							      <span lang="cs">Syntaxe</span>
							    </h2>
							  </section>
							</section>

							<section>
							  <section id="basic">
							    <h2>
							      <span lang="en">Basic usage</span>
							      <span lang="cs">Jednoduché použití</span>
							    </h2>
							  </section>
							</section>

							...
						

							#!/usr/bin/awk -f

							/<section id="toc">/,/<\/section>/ {
							  if ( /lang="/ ) lang = gensub( ".*lang=\"([^\"]+)\".*", "\\1", 1 )
							  if ( /li/ ) {
							    fragment = gensub( ".*#([^\"]+).*", "\\1", 1 )
							    if (lang == "en") {
							      frags[fidx++] = fragment
							    }
							    x = idx[lang]++
							    text = gensub( ".*>([^<]+)</a.*", "\\1", 1 )
							    item[x, lang] = text
							  }
							}

							END {
							  PROCINFO["sorted_in"] = "@ind_str_asc"
							  for (key in frags) {
							    print "<section>"
							    print "\t<section id=\"" frags[key] "\">"
							    print "\t\t<h2>"
							    print "\t\t\t<span lang=\"en\">" item[key, "en"] "</span>"
							    print "\t\t\t<span lang=\"cs\">" item[key, "cs"] "</span>"
							    print "\t\t</h2>"
							    print "\t</section>"
							    print "</section>"
							    print ""
							  }
							}
						
AWK TOC processing