rust-sed#
A GNU sed-compatible stream editor written in Rust.
Status#
61/61 tests passing (100%) against the upstream GNU sed 4.9 shell test suite. Six additional tests require locale or encoding configuration beyond the scope of this project (see excluded tests).
Usage#
Run a single upstream test:
nix build .#checks.x86_64-linux.rust-sed-test-{name}
View a failing test's log:
nix log .#checks.x86_64-linux.rust-sed-test-{name}
The binary is available as sed from pkgs.rust-sed (release build) or
pkgs.rust-sed-dev (debug build, faster compile).
Architecture#
Five source modules:
types— core types (SedRegex,Address,Command, …).parser— sed-script parser that producesCommandtrees.regex_util— BRE-to-ERE translation and POSIX character class fixups.engine— execution engine: cycle loop, command dispatch, address handling, append/prepend queues.util— small helpers: escape tokenization, control-character mapping.
Features#
Commands#
- All standard commands:
s,y,a/i/c,d/D,p/P,n/N,g/G/h/H/x,b/t/T,r/R,w/W,l,=,q/Q,:label,{...}. - GNU extensions:
e(execute),F(filename),v(version),Q(quiet quit). a\/i\/c\multi-line text continuation.#nquiet mode and inline#comments.
Substitution (s///)#
- Flags:
g,p,N(nth match),i/I(case-insensitive),m/M(multi-line regex),e(execute),w file. - Replacement:
\0–\9backreferences,&,\U/\L/\u/\l/\Ecase conversion,\n/\t/\\escapes,\c/\d/\o/\xchar escapes. - Duplicate-flag detection, backreference count validation.
Addresses#
N(line),$(last line),0(pre-first, forr).+N(relative),~N(multiple),first~step(arithmetic progression)./regex/withI/Mmodifiers; empty//reuses the last regex.- Two-address ranges with correct end-check semantics: ranges re-close cleanly even when branches skip past the end-line.
!negation with correct duplicate-!diagnostics.
Regex compatibility#
- Dot (
.) matches any character including\ninside pattern space (GNU sed behavior). - BRE:
^/$are anchors only at the very start/end of the pattern; literal characters elsewhere (POSIX BRE rule). fancy-regexfallback engine for patterns with backreferences.- POSIX character-class handling:
[is literal,\treatment differs between default and--posixmode,[:class:]parsing with unterminated- class detection.
Encoding#
- Script files: UTF-8 when valid, Latin-1 byte-preserving fallback so raw
bytes (
\xc4, …) survive the round trip. - Input files: raw-byte preservation for non-UTF-8 data; Latin-1 output encoding reproduces the original bytes.
- Parser is UTF-8-aware: multi-byte characters are preserved as single Unicode code points.
\d/\o/\xescapes produce raw bytes;\d/\ovalues > 255 wrap modulo 256.
Control flow#
- Labels may live anywhere, including nested inside
{...}blocks. A branch to a nested label enters the block at that label and resumes after the block on normal return. N/nflush the append queue before reading the next line (GNU sed compat).Dclears the suppress flag soP;Dpatterns print correctly.- Pre-print queue for
rwith address0(emit file contents before the first line of input).
I/O#
- In-place editing with
-i[SUFFIX],*expansion, backup file creation. --follow-symlinksresolves symlinks forFand in-place editing.- FIFO/device detection for in-place targets.
-uunbuffered mode: byte-by-byte stdin reads via raw fd.-znull-data mode: NUL-separated records.lcommand with configurable width (-l N,COLSenv var) that keeps multi-byte escape sequences atomic across line breaks.- Trailing-newline preservation (no spurious
\nif the input had none).
Validation & errors#
- GNU sed error format:
sed: -e expression #N, char M: ...with exit code 1. - Compile-time detection of: undefined branch labels, unterminated
s///, unterminateda/c/itext blocks (including across-eboundaries), unmatched},}with an address,+N/~Nas a first address, missing command after address at EOF, duplicatesflags, multiple!,#with an address, unknownsoptions, one-address-only violations in POSIX mode. vcommand version check against 4.9.
Modes#
--posix: rejects GNU extensions (extra commands,sflags,lwidth, address0,\l/\ucase conversion, etc.), enforces\aftera/c/i.--sandbox: compile-time rejection ofe,r,w.-E/-r: extended regex syntax.
Test inventory#
Tests excluded from harness#
These require locale or encoding configuration that is not worth wiring through the build:
8bit— non-UTF-8 binary input file.badenc— requires a specific locale.help-version— requires exact GNU version strings.invalid-mb-seq-UMR— requires a specific locale.newjis— requires a Japanese shift-JIS locale.utf8-ru— requires a Russian UTF-8 locale.