From 353d7edd938b64a73cefd97e67c135254dedafc9 Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Wed, 7 Oct 2026 12:49:06 +0000 Subject: [PATCH] feat(awk): run gawk, mawk and nawk as the awk builtin Claude-Session: https://claude.ai/code/session_019aFikmptPc91Fj4N2iDXQA --- crates/bashkit/docs/compatibility.md | 2 +- crates/bashkit/src/interpreter/mod.rs | 3 ++ .../tests/spec_cases/bash/awk-aliases.test.sh | 33 +++++++++++++++++++ knowledge/log.md | 1 + knowledge/status/builtins.json | 14 +++++++- 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 crates/bashkit/tests/spec_cases/bash/awk-aliases.test.sh diff --git a/crates/bashkit/docs/compatibility.md b/crates/bashkit/docs/compatibility.md index e09bb37ca..9653e404b 100644 --- a/crates/bashkit/docs/compatibility.md +++ b/crates/bashkit/docs/compatibility.md @@ -73,7 +73,7 @@ for sandbox security reasons. See the compliance spec for details. | `grep` | `-i`, `-v`, `-c`, `-n`, `-E`, `-q` | Pattern matching | | `rg` | `-i/-S/-s`, `-n/-N`, `--column`, `-b/--byte-offset`, `--vimgrep`, basic `--json`, `--stats`, `--null`, `-c`, `--count-matches`, `--include-zero`, `-l`, `--files-with-matches`, `--files-without-match`, `--files`, `-F`, `-w`, `-x`, `-a/--text`, `--binary`, `-m`, `-M/--max-columns`, `--max-columns-preview`, `--max-depth`, `-A`, `-B`, `-C`, separator flags, `--heading/--no-heading`, `--sort/--sortr`, `--path-separator`, `-g/--glob`, `--ignore-file`, `.ignore`/`.gitignore`, `--no-ignore*`, `--require-git/--no-require-git`, `-u/--unrestricted`, `--messages/--no-messages`, `-t/--type`, `-T/--type-not`, `--type-add`, `--type-clear`, `--type-list`, `--hidden/--no-hidden`, `-o`, `-q`, `-e`, `-f`, `-E/--encoding` (`auto`, `none`, UTF-8, UTF-16LE/BE), `-r`, `--passthru`, `--trim`, `-H/-I`, `--no-config`, `--line-buffered`, `--block-buffered`, `--mmap/--no-mmap`, `-P/--pcre2`, `--no-pcre2`, `--engine`, `--auto-hybrid-regex`, `--no-auto-hybrid-regex`, `--help`, `--version` | Recursive ripgrep-style search | | `sed` | `s///[gpiImMN w]`, `y`, `d`, `D`, `p`, `P`, `n`, `N`, `q[N]`, `Q[N]`, `=`, `l[N]`, `z`, `F`, `a`, `i`, `c`, `r`, `R`, `w`, `W`, `h/H/g/G/x`, `b`/`t`/`T`/`:label`, `{}`, `#`/`#n`; addresses `N`, `$`, `/re/[IM]`, `\cREc`, `first~step`, `a,b`, `a,+N`, `a,~N`, `0,/re/`, `!`; options `-n -e -f -i[SUF] -E/-r -s -z -l N -u --` and long forms | Stream editing; one stream across operands unless `-s`/`-i` | -| `awk` | `'{print}'`, `-F`, `-v`, loops, arrays, increment, ternary | Text processing | +| `awk` (also `gawk`, `mawk`, `nawk`) | `'{print}'`, `-F`, `-v`, loops, arrays, increment, ternary | Text processing | | `jq` | `.field`, `.[n]`, pipes, file args, `-r`, `-c`, `-n`, `-s`, `-S`, `-e`, `-j`, `-f`/`--from-file`, `--tab`, `--arg`, `--argjson`, `-V`, combined flags | JSON processing | | `sleep` | `N`, `N.N` | Pause execution (max 60s) | | `head` | `-n N`, `-N` | First N lines (default 10) | diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index 25e14f422..d4caccf3c 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -1634,6 +1634,9 @@ impl Interpreter { "grep" => Grep, "sed" => Sed, "awk" => Awk, + "gawk" => Awk, + "mawk" => Awk, + "nawk" => Awk, "head" => Head, "tail" => Tail, "sort" => Sort, diff --git a/crates/bashkit/tests/spec_cases/bash/awk-aliases.test.sh b/crates/bashkit/tests/spec_cases/bash/awk-aliases.test.sh new file mode 100644 index 000000000..fe1fb8b9b --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/awk-aliases.test.sh @@ -0,0 +1,33 @@ +# gawk, mawk and nawk run the awk builtin, so scripts that call a +# specific implementation by name keep working. + +### mawk_runs_awk +echo "a b" | mawk '{print $2}' +### expect +b +### end + +### gawk_runs_awk +### bash_diff: gawk is not installed on the reference host +echo "a b" | gawk '{print toupper($1)}' +echo x | gawk '{print gensub(/x/, "y", "g")}' +### expect +A +y +### end + +### nawk_runs_awk +### bash_diff: nawk is not installed on the reference host +nawk 'BEGIN{print 1+2}' +### expect +3 +### end + +### awk_aliases_resolve +### bash_diff: gawk/nawk are not installed on the reference host +for c in gawk mawk nawk; do type -t "$c"; done +### expect +file +file +file +### end diff --git a/knowledge/log.md b/knowledge/log.md index 2375d2dc1..80c7fce69 100644 --- a/knowledge/log.md +++ b/knowledge/log.md @@ -2,6 +2,7 @@ ## 2026-10-07 +* **Feature**: `gawk`, `mawk` and `nawk` run the awk builtin (same engine, including gawk extensions it already had such as `gensub`, `toupper`). Gap telemetry showed agents probing `gawk` by name. `--version` still identifies as bashkit awk. * **Fix**: `tar -P`/`--absolute-names` keeps the leading `/` (no notice), `-T FILE`/`--files-from` reads member names (blank lines skipped, `-` is stdin), and `--` ends options. `ls` implements the quoting styles: `-b`/`--escape`, `-N`, `-Q`, `--quoting-style=literal|escape|c|shell|shell-always|shell-escape|shell-escape-always` (GNU rules, including `"it's"` and headers left unescaped under `-b`); `locale`/`clocale` still report not implemented. Found by gap telemetry. * **Fix**: Arithmetic assigns to array elements. `((a[i]++))`, `((c[$k]+=3))`, `((a[2]=5))`, `((--a[0]))`, `let a[1]++` and `$((c[x]--))` read and write the element (indexed subscripts are arithmetic and accept negative indexes; associative keys are literal, quotes dropped as in `((c["x y"]++))`). Before, the update was lost or written to a scalar. Writes go through the budgeted `${a[i]:=v}` writer, so array memory limits still apply. Found by gap telemetry. * **Fix**: Gaps from the replayed agent calls: `set -n` / `set -o noexec` now stops running the rest of the script, as in bash (it was accepted and ignored); `find -ls` prints GNU's `ls -dils` layout; `tar -c` stores absolute paths without the leading `/` (with GNU's `Removing leading` notice) and `tar -cv` lists members on stdout unless the archive goes to stdout. Specs: `set-noexec.test.sh`, `find.test.sh`, `tar.test.sh`. diff --git a/knowledge/status/builtins.json b/knowledge/status/builtins.json index 948c09287..45ea6b965 100644 --- a/knowledge/status/builtins.json +++ b/knowledge/status/builtins.json @@ -285,6 +285,10 @@ "feature": null, "name": "free" }, + { + "feature": null, + "name": "gawk" + }, { "feature": null, "name": "getconf" @@ -429,6 +433,10 @@ "feature": null, "name": "mapfile" }, + { + "feature": null, + "name": "mawk" + }, { "feature": null, "name": "md5sum" @@ -457,6 +465,10 @@ "feature": null, "name": "nano" }, + { + "feature": null, + "name": "nawk" + }, { "feature": null, "name": "nice" @@ -882,5 +894,5 @@ "name": "zip" } ], - "count": 220 + "count": 223 }