Wawk Language Specification

Version 1.2.0 — A complete reference for the Wawk language: POSIX AWK fundamentals plus Wawk extensions. Every section includes a runnable example where noted. Edit the code and press Run to execute it as real WebAssembly in your browser.

Part 1: POSIX AWK Part 2: Wawk Extensions

Patterns

Every AWK program consists of pattern-action pairs. A pattern selects which input lines to process. An action executes when the pattern matches. If no pattern is given, the action runs for every line.

Syntax

/regex/ { action } expression { action } pattern1, pattern2 { action } # range { action } # every line

Try It

Patterns
Loading...
script.awk
input.txt
stdout
Press Run to execute

Fields & Records

AWK splits each input line (record) into fields automatically. $1 is the first field, $2 the second, and so on. $0 is the entire line. NF holds the number of fields, NR the record number.

Syntax

$1 # first field $NF # last field $0 # entire record NF # field count NR # record number FS # input field separator (default: space) OFS # output field separator (default: space)

Try It

Fields
Loading...
script.awk
input.txt
stdout
Press Run to execute

Variables & Assignment

AWK variables are dynamically typed. They hold numbers or strings depending on context. Variables are initialized to 0 or empty string automatically.

Syntax

x = 42 # numeric name = "Alice" # string x = x + 1 # increment $1 = toupper($1) # modify field

Try It

Variables
Loading...
script.awk
input.txt
stdout
Press Run to execute

Regular Expressions

AWK uses extended regular expressions. Patterns between /.../ are regex matches against $0. The ~ and !~ operators test specific fields.

Syntax

/^[A-Z]/ # starts with uppercase /error|warn/ # alternation $1 ~ /^[0-9]+$/ # field matches digits $2 !~ /tmp/ # field does not match

Try It

Regex
Loading...
script.awk
input.txt
stdout
Press Run to execute

BEGIN & END

BEGIN runs once before any input is read. END runs once after all input is processed. Use them for initialization, headers, summaries, and final calculations.

Syntax

BEGIN { # init, print header } /pattern/ { # process each line } END { # summary, print footer }

Try It

BEGIN/END
Loading...
script.awk
input.txt
stdout
Press Run to execute

Associative Arrays

AWK arrays are hash maps. Indices can be any string. Use for (key in array) to iterate. Common patterns: word count, group-by, frequency analysis.

Syntax

arr[key] = value # set arr[key]++ # increment key in arr # test membership delete arr[key] # remove element for (k in arr) ... # iterate

Try It

Arrays
Loading...
script.awk
input.txt
stdout
Press Run to execute

Built-in Functions

Wawk provides all POSIX AWK built-in functions plus Wawk extensions for type inspection, bitwise operations, time handling, and advanced string processing.

String Functions

length(s) # string length (or $0 if omitted) substr(s, start, len) # substring of s starting at position start index(s, t) # position of t in s (0 if not found) split(s, arr, fs) # split s into array by separator fs sub(r, t, s) # substitute first match of regex r with t gsub(r, t, s) # substitute all matches of regex r with t match(s, r) # position of first match of regex r in s sprintf(fmt, ...) # format string (like printf but returns string) toupper(s) / tolower(s) # case conversion patsplit(s, arr, pat) # split by pattern matches into array (gawk ext)

Math Functions

int(x) # truncate to integer (toward zero) sqrt(x) # square root exp(x) # exponential (e^x) log(x) # natural logarithm sin(x) # sine (x in radians) cos(x) # cosine (x in radians) atan2(y,x) # arctangent of y/x (in radians) rand() # random number in [0, 1) srand(n) # seed for rand() (returns previous seed) abs(x) # absolute value (Wawk extension)

Try It

Functions
Loading...
script.awk
input.txt
stdout
Press Run to execute

User-Defined Functions

Define custom functions with the function keyword. Functions can take parameters and return values. Local variables are declared as extra parameters (convention).

Syntax

function name(params) { # body return value } # Local variables: extra params function max(a, b, _tmp) { return (a > b) ? a : b }

Try It

User Functions
Loading...
script.awk
input.txt
stdout
Press Run to execute

Control Flow

AWK supports if/else, while, for, and do-while loops. break and continue work as expected. The ternary operator is available for inline conditionals.

Syntax

if (cond) stmt if (cond) stmt else stmt while (cond) stmt for (init; test; incr) stmt do stmt while (cond) break / continue cond ? val1 : val2

Try It

Control Flow
Loading...
script.awk
input.txt
stdout
Press Run to execute

Output & Formatting

print outputs fields separated by OFS, followed by ORS (newline). printf gives C-style formatting. Output can be redirected to files or pipes within AWK.

Syntax

print expr # print with ORS print a, b, c # separated by OFS printf fmt, args # formatted output print > "file" # redirect to file print | "cmd" # pipe to command

Try It

Output
Loading...
script.awk
input.txt
stdout
Press Run to execute

PropertyTree: Universal Data Model

Wawk extends AWK with PropertyTree — a universal structured data model that serves as the core representation for all structured input formats. Input is automatically detected and parsed into PropertyTree regardless of format: JSON (priority 10), XML (30), YAML (40), or CSV (50). Access object fields with $.field notation, array elements with $1, $2 positional access, and construct new structured data with object/array literals.

Syntax

# JSON is auto-detected — no import needed # Access nested fields with chained dot-notation { print $.customer.name, $.customer.address.city } # Array element access with bracket indexing { print $.items[0].product, $.items[0].price } # Positional access for top-level arrays $1, $2, $3 # array element by position print # auto-serializes PropertyTree back to JSON

Try It

PropertyTree-Native
Loading...
script.awk
input.txt
stdout
Press Run to execute

Multi-Format: Same Syntax, Any Input

The same $.field syntax works regardless of whether input is JSON, XML, YAML, or CSV. PropertyTree abstracts away the format — write once, process anything. Navigate nested structures with chained dot-access: $.address.city. Use typeof() to inspect value types at runtime. Each input record is parsed independently — for XML, use one element per line.

Format-Agnostic Code

# This code works with JSON, XML, YAML, or CSV input: { print $.customer.name, $.customer.address.city } # Array bracket indexing works in all formats $.items[0].product # JSON: {"items":[{"product":"Laptop"}]} # XML: <items><product>Laptop</product></items> # Object literal output — construct new JSON from extracted fields { print {name: $.customer.name, city: $.customer.address.city} } # Type introspection on nested fields { print typeof($.customer.name), typeof($.items) }

Try It — XML Input

PropertyTree: XML
Loading...
script.awk
input.txt (XML)
stdout
Press Run to execute

@include Directive

@include "file.awk" expands included files inline, enabling code reuse across scripts (gawk-compatible, max 16 levels nesting, circular include protection). For plugin loading via @plugin, see the Plugin page.

Syntax

@include "utils.awk" # inline-expand file at this point @include "lib/math.awk" # relative or absolute path # Max 16 levels of nested includes # Circular includes are detected and rejected

Try It

@include pattern
Loading...
script.awk
input.txt
stdout
Press Run to execute

typeof() & Literal Syntax

Wawk adds a typeof() function and literal syntax for structured data construction. These extensions allow AWK programs to work natively with typed values and build PropertyTree values inline.

typeof() Function

typeof(expr) # Returns one of: "number", "string", "array", # "object", "boolean", "null", "undefined" # Examples: typeof(42) # "number" typeof("hello") # "string" typeof(true) # "boolean" typeof(null) # "null" typeof([1,2,3]) # "array" typeof({"a": 1}) # "object"

Boolean & Null Literals

true / false # Boolean literals null # Null literal x = true if (x == true) print "yes" print typeof(null) # "null"

Object & Array Literals

# Object literal (creates PropertyTree::Object) person = {"name": "Alice", "age": 30, "active": true} print person.name # "Alice" print typeof(person) # "object" # Array literal (creates PropertyTree::Array) scores = [95, 87, 72, 63] print scores[0] # 95 print typeof(scores) # "array" # Nested construction data = { "users": [{"name": "Alice"}, {"name": "Bob"}], "count": 2 } print data.users[0].name # "Alice"

Try It

typeof & Literals
Loading...
script.awk
input.txt
stdout
Press Run to execute

I/O: print, printf & getline

print outputs fields separated by OFS, followed by ORS. printf provides C-style formatted output. getline reads the next record from input or from a pipe/file. Output can be redirected to files or piped to commands.

Syntax

print expr # print with ORS (default: newline) print a, b, c # separated by OFS (default: space) printf "%-10s %5d\n", name, val # C-style formatting print expr > "file" # redirect output to file print expr | "cmd" # pipe output to command getline # read next record from stdin getline var < "file" # read from file into var

Format specifiers

SpecifierMeaning
%sString
%dInteger
%fFloating point
%oOctal
%xHexadecimal
%e/%gScientific / shortest float
%%Literal %

Complete Function Reference

All built-in functions available in Wawk. POSIX functions work identically to standard AWK. Functions marked ext are Wawk extensions.

String Functions

FunctionDescriptionExample
length(s)Length of string s (or $0 if omitted)length("hello") → 5
substr(s, m, n)Substring of s starting at position m, length nsubstr("hello", 2, 3) → "ell"
index(s, t)Position of t in s (0 if not found)index("hello", "ll") → 3
split(s, a, fs)Split s into array a by separator fssplit("a:b:c", x, ":") → 3
sub(r, t, s)Substitute first match of r with t in s (or $0)sub(/o/, "0", "foo") → "f0o"
gsub(r, t, s)Substitute all matches of r with t in s (or $0)gsub(/o/, "0", "foo") → "f00"
match(s, r)Position of first match of regex r in s (0 if none)match("abc123", /[0-9]+/) → 4
sprintf(fmt, ...)Format string (like printf but returns string)sprintf("%03d", 7) → "007"
tolower(s)Convert to lowercasetolower("HELLO") → "hello"
toupper(s)Convert to uppercasetoupper("hello") → "HELLO"
patsplit(s, a, p, [s])Split by pattern matches extpatsplit("a1b2", x, /[0-9]/) → 2

Math Functions

FunctionDescription
int(x)Truncate to integer (toward zero)
sqrt(x)Square root
exp(x)Exponential (e^x)
log(x)Natural logarithm
sin(x)Sine (x in radians)
cos(x)Cosine (x in radians)
atan2(y, x)Arctangent of y/x (in radians)
rand()Random number in [0, 1)
srand(n)Seed for rand() (returns previous seed)
abs(x) extAbsolute value

I/O Functions

FunctionDescription
print ...Print arguments separated by OFS, terminated by ORS
printf fmt, ...Formatted output (C-style)
getline [var] < fileRead next record from file into var (or $0)
close(file)Close open file or pipe
fflush([file])Flush output buffer for file (or all files)
system(cmd)Execute shell command, return exit status

Type & Conversion Functions ext

FunctionDescription
typeof(val)Returns "number", "string", "boolean", "null", "object", "array", or "undefined"
is_null(val)Returns 1 if val is null, 0 otherwise
is_object(val)Returns 1 if val is an object, 0 otherwise
to_json(val)Serialize any value to JSON string
from_json(str)Parse JSON string into PropertyTree value

Bitwise Functions ext

FunctionDescription
and(a, b)Bitwise AND
or(a, b)Bitwise OR
xor(a, b)Bitwise XOR
compl(a)Bitwise complement (NOT)
lshift(a, n)Left shift a by n bits
rshift(a, n)Right shift a by n bits

Time Functions ext

FunctionDescription
systime()Current time as Unix timestamp
strftime(fmt [, ts])Format timestamp using C strftime format (default: now)
mktime(datespec)Parse "YYYY MM DD HH MM SS" to Unix timestamp

Array Functions

FunctionDescription
delete arr[key]Remove element from array
delete arrDelete entire array
(key in arr)Test if key exists in array

Built-in Variables

Wawk provides built-in variables that control input/output behavior and provide information about the current processing state.

VariableDescriptionDefault
$0Current record (entire line)
$1..$NFIndividual fields
NFNumber of fields in current record
NRTotal number of records processed0
FNRRecord number in current file0
FSInput field separator" " (whitespace)
OFSOutput field separator" " (space)
RSInput record separator"\n" (newline)
ORSOutput record separator"\n" (newline)
FILENAMEName of current input file"" (stdin)
ARGVCommand-line arguments array
ARGCNumber of command-line arguments
ENVIRONEnvironment variables (read-only associative array)
RSTARTStart position of last match() (1-based)0
RLENGTHLength of last match()-1
SUBSEPSubscript separator for multi-dimensional arrays"\034"

Extended I/O

Wawk extends POSIX I/O with append redirection, command piping, nextfile to skip to the next input file, and fflush() to flush output buffers.

I/O Extensions

print "data" >> "file.log" # append to file print "cmd" | "sort" # pipe output to command getline line < "input.txt" # read from file nextfile # skip remaining records in current file fflush() # flush all open output files fflush("file.log") # flush specific file close("file.log") # close file or pipe ERRNO # set on I/O failures

Extended Variables & Operators

Beyond POSIX variables (NR, NF, FS, OFS, RS, ORS, FILENAME), Wawk adds several built-in variables and operators.

Additional Built-in Variables

Variable Description
FNRRecord number within current file (reset per file)
ENVIRONAssociative array of environment variables (read-only)
FPATField pattern: regex describing field content (gawk extension)
CONVFMTConversion format for numbers (default "%.6g")
OFMTOutput format for numbers (default "%.6g")
RSTARTStart index of string matched by match()
RLENGTHLength of string matched by match()
SUBSEPSubscript separator for multi-dimensional arrays (default "\034")
ERRNOSet on I/O failures, plugin errors (Wawk extension)
ARGV / ARGCCommand-line arguments and count
true / false / nullBoolean and null literals (Wawk extension)

Extended Operators

x ** y # exponentiation (same as x ^ y) x ? a : b # ternary conditional !x # logical NOT ++x, x++ # pre/post increment --x, x-- # pre/post decrement expr ~ /re/ # regex match expr !~ /re/ # regex not-match

String Escapes & Hex Literals

Wawk supports the full range of C-style string escape sequences and hexadecimal number literals.

\n newline \t tab \r carriage return \\ backslash \" double quote \a alert/bell \b backspace \f form feed \v vertical tab \xNN hex escape (1-2 hex digits, e.g. \x41 = "A") \OOO octal escape (1-3 octal digits, e.g. \101 = "A") 0xFF # hex number literal (255) 0x1A # hex number literal (26)

Security Features

Wawk includes comprehensive security limits to prevent resource exhaustion and denial-of-service attacks. All limits are enforced at the engine level and apply across all platforms.

LimitValuePurpose
Output size64 MBPrevents unbounded output generation
Record size64 MBPrevents memory exhaustion from large records
Array size1,000,000Maximum entries per associative array
Object key limit10,000Maximum keys per PropertyTree object
Nesting depth64Maximum levels for structured data parsing
Field limit100,000Maximum fields per record
Open files256Maximum simultaneous file targets
Recursion depth256Maximum nested function calls
Loop iterations100MPrevents infinite loops
Audit log cap1,024Prevents audit bomb attacks
Regex cache512LRU eviction for compiled regex patterns
Printf width/precision10,000Caps format string width and precision

Additional security measures: NFA-based regex engine (no ReDoS vulnerability), Wasm sandbox isolation (no network, filesystem, or system command access from plugins), safe UTF-8 conversion (no unsafe blocks in hot paths), field index clamping (prevents overflow from very large f64 values), and configurable execution timeout with amortized checks.

Performance Optimizations

Wawk includes numerous performance optimizations that make it competitive with traditional AWK implementations while running in WebAssembly.

Zero-allocation hot paths
Reusable buffers for print output, array keys, and split results avoid per-record heap allocations.
Fast number formatting
Uses itoa for integers and ryu for floats, avoiding format! overhead.
Literal pattern fast-path
Substring search instead of regex engine for literal-only patterns.
Regex compilation cache
LRU eviction with max 512 entries. Static patterns compiled once before main loop.
Deferred field materialization
Byte ranges into line buffer — no String allocation per field until accessed.
Single-pass whitespace splitting
Merged whitespace detection and field splitting into one pass.
Format auto-detection skip
First-byte check eliminates per-record trait dispatch for plain text input.
Scope stack
Zero-copy variable scoping for user-defined functions via stack-based scope frames.
FxHashMap
Fast hashing (FxHash) for associative arrays and variable lookup.
Single-hot-rule dispatch
Bypasses rule loop for single-pattern programs — direct execution path.
Ultra-fast print $N
Zero-copy direct write for constant field index access.
Leaf expression depth skip
Expression depth check bypassed for leaf nodes (Number, String, Var).