Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/bashkit/docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
3 changes: 3 additions & 0 deletions crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,9 @@ impl Interpreter {
"grep" => Grep,
"sed" => Sed,
"awk" => Awk,
"gawk" => Awk,
"mawk" => Awk,
"nawk" => Awk,
"head" => Head,
"tail" => Tail,
"sort" => Sort,
Expand Down
33 changes: 33 additions & 0 deletions crates/bashkit/tests/spec_cases/bash/awk-aliases.test.sh
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions knowledge/log.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
14 changes: 13 additions & 1 deletion knowledge/status/builtins.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@
"feature": null,
"name": "free"
},
{
"feature": null,
"name": "gawk"
},
{
"feature": null,
"name": "getconf"
Expand Down Expand Up @@ -429,6 +433,10 @@
"feature": null,
"name": "mapfile"
},
{
"feature": null,
"name": "mawk"
},
{
"feature": null,
"name": "md5sum"
Expand Down Expand Up @@ -457,6 +465,10 @@
"feature": null,
"name": "nano"
},
{
"feature": null,
"name": "nawk"
},
{
"feature": null,
"name": "nice"
Expand Down Expand Up @@ -882,5 +894,5 @@
"name": "zip"
}
],
"count": 220
"count": 223
}
Loading