Skip to content

sed: take the -i suffix only when attached, as GNU sed does - #583

Merged
sylvestre merged 2 commits into
uutils:mainfrom
DePasqualeOrg:fix-in-place-detached-suffix
Sep 29, 2026
Merged

sylvestre merged 2 commits into
uutils:mainfrom
DePasqualeOrg:fix-in-place-detached-suffix

Conversation

@DePasqualeOrg

@DePasqualeOrg DePasqualeOrg commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Claude Code and Codex flagged this gap during my work with this project. The changes here have gone through extensive automated review. I'm happy to make changes as needed or close this PR and maintain it as a private patch if it doesn't meet your standards.


-i took the next argument as its backup suffix, so in sed -i SCRIPT FILE..., the usual GNU form, the first file name became the script. This usually fails, but when the name happens to be a valid command, sed applies it to the remaining files and exits with 0:

$ sed -i 's|80|8080|' config.yaml deploy.yaml
before: exit 0, config.yaml unchanged, every line of deploy.yaml replaced by "onfig.yaml"
after:  8080 in both files

As in GNU sed, the suffix must now be attached (-i.bak, --in-place=.bak). The in-place option now sets require_equals, and an attached -iSUFFIX is rewritten to --in-place=SUFFIX before clap parses, including inside clusters such as -ni.bak. The values of other options are left alone, and -e, -f and -l now accept values that begin with -, as in GNU sed, so sed -f -ifoo.sed file reads its script from -ifoo.sed. This drops BSD's detached -i '' and -i .bak, which GNU sed reads as a script or file name, and docs/src/extensions.md now says so. The GNU testsuite's inplace-hold and stdin-prog tests now pass.

This builds on #433 by @MukundaKatta, which was left unfinished, and adds handling of clusters and --.

Fixes #165, fixes #229, fixes #425, fixes #549.

@github-actions

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 16 / FAILED: 41 / SKIPPED: 8
  Reference: TOTAL: 65 / PASSED: 14 / FAILED: 43 / SKIPPED: 8

Changes from main branch:
  TOTAL: +0
  PASSED: +2
  FAILED: -2

Test improvements (2):
  + cmd-R
  + inplace-hold

@codecov

codecov Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.28571% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 83.97%. Comparing base (dfae00d) to head (f6c9934).

Files with missing lines Patch % Lines
src/sed/mod.rs 99.28% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #583      +/-   ##
==========================================
+ Coverage   83.67%   83.97%   +0.30%     
==========================================
  Files          14       14              
  Lines        7067     7201     +134     
  Branches      413      417       +4     
==========================================
+ Hits         5913     6047     +134     
  Misses       1149     1149              
  Partials        5        5              
Flag Coverage Δ
macos_latest 85.09% <99.28%> (+0.29%) ⬆️
ubuntu_latest 85.28% <99.28%> (+0.28%) ⬆️
windows_latest 0.00% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed

codspeed Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 2.07%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 9 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ access_log_subst 2.2 s 2.4 s -5.98%
⚡ no_op_short 2.4 s 2.4 s +2%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing DePasqualeOrg:fix-in-place-detached-suffix (f6c9934) with main (dfae00d)

Open in CodSpeed

@DePasqualeOrg
DePasqualeOrg force-pushed the fix-in-place-detached-suffix branch from bb946b1 to f6c9934 Compare September 29, 2026 15:02
@DePasqualeOrg
DePasqualeOrg marked this pull request as ready for review September 29, 2026 15:13
@github-actions

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 16 / FAILED: 41 / SKIPPED: 8
  Reference: TOTAL: 65 / PASSED: 14 / FAILED: 43 / SKIPPED: 8

Changes from main branch:
  TOTAL: +0
  PASSED: +2
  FAILED: -2

Test improvements (2):
  + cmd-R
  + inplace-hold

Comment thread src/sed/mod.rs Outdated
let mut args = args.into_iter();
// The program name.
let mut out: Vec<OsString> = args.next().into_iter().collect();
for arg in args.by_ref() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a detached value isn't skipped here: sed -f -ifoo.sed file would become -f --in-place=foo.sed
GNU reads -ifoo.sed as the script file
edge case, but could you please skip the next arg after -e/-f/-l and add a test? thanks

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. This also required letting -e, -f and -l accept values starting with -, as GNU sed does.

Comment thread src/sed/mod.rs Outdated
}

#[test]
fn test_in_place_suffix_forms() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these unit tests mostly repeat the tests in tests/by-util/test_sed.rs
do we need both? i'd keep the gnu_in_place_args rewrite cases and the integration tests

Comment thread tests/by-util/test_sed.rs Outdated
.args(&[arg, "s/world/universe/p", path.to_str().unwrap()])
.succeeds();

let expected = if arg == "-ni.bak" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please put the expected output in the array with the arg instead of this if

@sylvestre
sylvestre merged commit 75fbaca into uutils:main Sep 29, 2026
1 check passed
@sylvestre

Copy link
Copy Markdown
Contributor

Thanks for your PR

@DePasqualeOrg
DePasqualeOrg deleted the fix-in-place-detached-suffix branch September 29, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants