Words. Both shells: dash 0.5.12 and bash --posix 5.2.21. The parser: Proc::ShellSubset::Large. The executor: Proc::ShellSpawn, which runs the parsed strings. The detector: doc/large-subset/tools/large-subset-features.pl, which finds differences between the shells in a sample's text, and adds ShellCheck's warnings about constructs dash lacks.
What keeps Proc::ShellSubset::Large (the large parser) from accepting more of the corpus samples, and what to do about it. The samples: one-line commands from tldr and NL2Bash, scripts from the bash Cookbook, the pure-sh and pure-bash bibles, commands from the book Managing Projects with GNU Make (left out below, as a noisy extraction), and ShellCheck's test strings, split into "clean" (strings ShellCheck's tests expect no warning for) and "warned" (strings its tests expect a warning for). Details: doc/large-subset/large-subset-state.md.
The yardsticks (R3, second version: decided by the shells, with bash's manual and ShellCheck as aids, never by our parser; see Y1). Upper, "nothing bogus found": both shells parse the sample (dash -n, bash --posix -n), and it uses no blatant difference between them. Lower, "compatible": in addition, it uses no subtle difference. Where the subset runs a program in place of both shells' builtin (echo, printf, test, [, kill, time; also pwd, true, false, where the shells agree anyway), the program decides, and the shells' difference excludes nothing. Measured on 2026-11-03 with version 0.03 (B1–B3, P5, R1, Y2, Y3 and Q1 done), after leaving out duplicates, 163 tldr lines made only of keystrokes, 59 tldr lines with keystrokes next to other text (Y3), the make book, and 16 ShellCheck test strings that are wrong where they stand (return outside a function and the like, which ShellCheck's own tests mark as errors):
| Source | Samples | Accepted | Lower | Upper | Within lower, rejected | Accepted outside upper |
|---|---|---|---|---|---|---|
| tldr | 29,450 | 99.2% | 99.2% | 99.3% | 23 | 1 |
| NL2Bash | 10,624 | 93.9% | 94.5% | 94.8% | 76 | 3 |
| bash Cookbook | 81 | 32.1% | 27.2% | 35.8% | 0 | 0 |
| pure-sh-bible | 44 | 97.7% | 95.5% | 100.0% | 0 | 0 |
| pure-bash-bible | 122 | 40.2% | 41.8% | 41.8% | 2 | 0 |
| ShellCheck, clean | 879 | 60.3% | 62.6% | 66.0% | 34 | 0 |
| ShellCheck, warned | 766 | 58.5% | 61.5% | 62.3% | 28 | 1 |
"Accepted" can exceed "Lower": an accepted sample with a subtle difference counts against the lower yardstick, because the subset gives only one of the two behaviours. The 5 samples accepted outside the upper yardstick are misreadings by the detector, not parser errors. After Y2, Y3 and B1–B3 the parser still rejects 163 samples within the lower yardstick (304 the day before); they are listed, with what decides each kind, in doc/large-subset/large-subset-state.md, section 4. The interactive-only builtins of B2, which now do nothing by your decision, count like the programs: the shells' difference is settled by a decision of ours.
Loading marks…