Skip to content

feat(coreutils): add sed - #443

Closed
raphaelvigee wants to merge 1 commit into
raphaelvigee/coreutils-archivesfrom
raphaelvigee/coreutils-sed
Closed

feat(coreutils): add sed#443
raphaelvigee wants to merge 1 commit into
raphaelvigee/coreutils-archivesfrom
raphaelvigee/coreutils-sed

Conversation

@raphaelvigee

Copy link
Copy Markdown
Member

@raphaelvigee
raphaelvigee force-pushed the raphaelvigee/coreutils-archives branch from 04df5d1 to 1f8ae6f Compare August 29, 2026 22:44
@raphaelvigee
raphaelvigee force-pushed the raphaelvigee/coreutils-sed branch from 1cd7454 to 1dedd2a Compare August 29, 2026 22:44
@raphaelvigee
raphaelvigee force-pushed the raphaelvigee/coreutils-archives branch from 1f8ae6f to 5fe0785 Compare September 3, 2026 16:26
@raphaelvigee
raphaelvigee force-pushed the raphaelvigee/coreutils-sed branch from 1dedd2a to a8bd0a9 Compare September 3, 2026 16:26
The sharpest divergence in the set. GNU's `-i` takes an optional attached
suffix and BSD's requires a separate one, so `sed -i 's/a/b/' f` edits the
file on Linux and eats the next argument as a filename on macOS. heph
takes GNU's form and refuses BSD's with the fix spelled out, rather than
silently treating `''` as the script and doing nothing — which is exactly
the failure this applet exists to remove.

No embeddable POSIX sed exists in Rust, so this one is written here over
the `regex` crate, which has no backreferences and no lookaround by
design. The rule for that gap is reject loudly, never approximate: an
unsupported construct is an error naming it, never a silently different
match. A wrong sed that keeps going is far worse than one that stops.

Basic regular expressions are supported by translating them to the
extended syntax the engine speaks — `\(` becomes `(`, a bare `+` becomes
`\+`, and bracket expressions pass through untouched because nothing
inside them follows either set of rules. Without that translation the
most common idiom in real scripts, `s/\(a\)\(b\)/\2\1/`, would not
compile, and "reject loudly" would mean rejecting almost everything.

Supported: s (with g, p, i and a numeric flag), y, d, p, q, =, a, i, c;
addresses by line, `$`, /re/, ranges and `!`; -n, -e, -f, -i[SUFFIX],
-E/-r. Command groups are refused rather than half-supported. Both `a
text` (GNU) and `a\` + newline (BSD) are accepted, since the point is
that one script runs on both hosts.

In-place editing writes through a temporary in the same directory and
renames: a truncate-then-write loses the file if anything fails halfway,
and this is editing someone's source.

Verified against the host's GNU sed: fourteen scripts covering
substitution flags, alternate delimiters, BRE groups, every address form,
negation, `q` and `y` all produce byte-identical output.

COREUTILS_VERSION 3 -> 4: the applet set changed. The set is now complete.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0181d7hhbYWXT42Z1KQPM29Q
@raphaelvigee

Copy link
Copy Markdown
Member Author

Superseded by consolidation. The applet halves of this PR (#442 tar/gzip/zstd, #443 sed, #444's tmpl) now land in two PRs instead of four:

No content was dropped — the restacked tree is byte-identical to the eight-commit version, and every layer builds, lints and passes its unit tests on its own. Fewer layers also matters now that stacked PRs get no CI unless labelled (#449).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant