You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add raw string literals, like Rust's: r"C:\Program Files\Rust" is taken verbatim, backslashes are not escapes (no more "\\d+" in dynamic regexes: $0 ~ r"\d+"). To include ", put the same number of #s around the quotes: r#"say "hi""#, r##"a"#b"##. A raw string can span lines. Behavior change: r"..." (no space) is now a raw string, not the variable r concatenated with a string; write r "..." for the latter
Add the ??= operator: l ??= r is l ?? (l = r), so r is evaluated and assigned only when l is uninitialized, empty or zero (as for ??); the subscript of an array element is evaluated once. E.g. { OFS ??= ","; total[$1] ??= 0 }
Add the !in operator, like Kotlin's !in (Python's not in): k !in arr is !(k in arr), e.g. $1 !in seen { seen[$1]; print }; multi-dimensional keys work too: (i, j) !in arr
Add key-value iteration for (k, v in arr) body, like Python's for k, v in d.items(): the same as for (k in arr) { v = arr[k]; body }, e.g. END { for (k, v in cnt) print k, v }; on an array made by split it works like enumerate. arr must be an array variable: for (k, v in f()) is a syntax error (assign the result first: a = f(); for (k, v in a))
Add negative field indexes: $(-k) is $(NF + 1 - k), so $(-1) is $NF and $(-2) is $(NF-1). Reading before the first field gives "", assigning there is a fatal error; the parentheses are required ($-1 is a syntax error)
Add assert(cond, msg): when cond is false, print msg to stderr and exit at once with code 2, without running END (unlike exit 2), e.g. { assert(NF == 5, f"line {NR}: expect 5 fields, got {NF}") }
Add local variables: { local a = $1; ... } declares a for the rest of the rule (or function body), including nested blocks; it shadows a global a, which other rules still see. A local is uninitialized again on each run of the rule ({ local n; n++; print n } prints 1 for every record), local arr[] is an empty array, and local x = x + 1 reads the outer x. Several can be declared at once (local i, s = "", seen[]). In a function, locals are new on each call, like the extra-parameter idiom. Special variables (NR, FS, SUBSEP, ...) and function names cannot be local, a name cannot be declared twice in one local statement, and a scalar local used as an array is an error that suggests local x[]. Behavior change: local is a keyword and can no longer be used as a variable or function name (local = 1 and function local() are now syntax errors); rename such variables or functions
A failing stdlib function (database, HTTP, KV, S3, crypto, ...) now also sets ERRNO to its message (e.g. sqlite_query: no such table: users), and a network error of http_get/http_post (status 0) sets ERRNO to the reason, so ERRNO = ""; r = sqlite_query(db, sql); if (ERRNO != "") ... tells a failure from an empty result
Database functions take optional positional parameters: sqlite_query/sqlite_execute, libsql_*, mysql_* and pg_* accept an array as a third argument, bound in key order to a prepared statement (p[1] = $1; p[2] = $2; sqlite_execute(db, "insert into t values(?, ?)", p)), so values containing ' work and input data cannot inject SQL. Placeholders are ? (SQLite, libSQL, MySQL) or $1, $2... (PostgreSQL); PostgreSQL converts the text values to the inferred parameter types (bool, integers, floats, numeric, json, uuid, inet, bytea, date/time), with an empty value as NULL for non-text types. PostgreSQL error messages now include the cause (db error: ERROR: relation "t" does not exist) instead of only db error
-i jsonl/-i json: a key missing from the first record is no longer dropped. It gets the next column when a later record has it (NF grows from that record on) and is added to FI, so $FI[k] with a key only known at run time finds it; a scalar first record no longer leaves the later objects with NF=0
Behavior change: s3_get/s3_put failures are a warning and an empty result, like other stdlib functions, instead of a fatal panic