Reads and writes
- CSV / TSV
- JSON Lines
- Parquet
- Excel
- Markdown
- SQLite
- MySQL
- PostgreSQL
- S3
- HTTP
- NATS
- gz · zst · xz
Everything AWK was missing
Fast by design
Type inference and a Cranelift JIT turn AWK into machine code, with SIMD CSV parsing and parallel execution. Usually 2-8x faster than gawk on large files.
zawk -i csv -p r -j 8 '{ s += $3 } END { print s }' big.csvStructured data, by name
RFC 4180 CSV, TSV, JSON Lines, Parquet, Excel and Markdown tables, with columns by name through $FI["col"]. Write CSV, JSON Lines, Parquet or Markdown.
zawk -i jsonl -o md '{ print $FI["name"], $FI["age"] }' users.jsonlA real standard library
~190 functions: text, JSON/XML/HTML, dates, crypto and JWT, IDs, statistics, HTTP, email and S3. Failures warn and set ERRNO instead of crashing.
{ print url($1)["host"], json_value($2, "$.id"), uuid("v7") }Databases as input
Read a SQLite, MySQL or PostgreSQL table or query like a CSV file, and write back with bound parameters. Redis and NATS KV are one call away.
zawk '{ print $FI["name"] }' 'postgres://u:p@host/db#people'Streams and messages
Subscribe to a NATS subject as input, then publish to NATS or MQTT. A ten-line AWK script becomes a message processor.
zawk -i json '{ publish(out, MSG_BODY) }' 'nats://localhost:4222/logs.>'Made for AI agents
zawk llm writes the prompt, zawk lint checks the answer as JSON, and jev asks an LLM typed questions per record. A Claude Code skill is included.
zawk llm -i csv -H sales.csv 'top 3 regions?' | claude -pModern syntax, still AWK
f-strings, raw strings, ??, try … else, match expressions,local variables, key-value loops, ranges, !in and negative field indexes. Existing AWK programs keep their meaning.
- f-strings
- match
- try / ??
- local & loops
{ print f"{NR:>4}: {toupper($2):<10} {$3 * 1.1:,.2f}" }
{ sql = f"SELECT * FROM {table} WHERE id = {$1}" }
{
level = match $3 {
/^E/ => "error",
"warn" | "W" => "warn",
/(\d+)ms/ as m => m[1] > 1000 ? "slow" : "ok",
_ => "info"
}
}
{
name = $FI["nick"] ?? "Guest"
body = try read_all($FI["url"]) else ""
rows = try pg_query(db, sql) else fail(ERRNO)
}
{ local total = 0, seen[] }
$1 !in seen { seen[$1]; print $(-1) }
END {
for (word, n in count) print word, n
for (i in 1..=10) print i
}
Start with a one-liner
Install zawk and point it at a file you already have.