Skip to content

Implement e (execute) command#481

Open
PranavRJoshi wants to merge 6 commits into
uutils:mainfrom
PranavRJoshi:feat/e-comm
Open

Implement e (execute) command#481
PranavRJoshi wants to merge 6 commits into
uutils:mainfrom
PranavRJoshi:feat/e-comm

Conversation

@PranavRJoshi

Copy link
Copy Markdown
Contributor

Fixes #476.

Implements the standalone e command (a GNU extension). Supports the command with and without arguments.

Changes:

  • Added the e command in compiler.rs/processor.rs, both forms (with argument, bare/pattern-space). Argument parsing reuses the same escape decoding and backslash continuation as a/c/i, as GNU sed's e argument follows the same syntax.
  • Rejected under --posix and --sandbox at compile time.
  • Fixed e and s///e to silently swallowing the child shell's stderr.
  • Added 17 tests covering both command forms, addressing, ';' not separating the argument, escape decoding, backslash continuation, --posix/--sandbox rejection, and stderr surfacing on failure.

Irrelevant: fixed a typo found at delimited_parser.rs.

Implement the 'e' command. No argument implies execution of pattern space and any respective argument is to run with the output written to stream. Rejected under --posix and --sandbox.

Also stop silently swallowing shell stderr for e and s///e.

Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
Includes 17 new tests. Cover both forms of the new 'e' command: with-argument execution (including shell side effects, addressing, ';' not separating the argument, escape decoding, and backslash continuation) and the no-argument pattern-space form. Also cover --posix/--sandbox rejection and stderr surfacing on command failure.

Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 112 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.79%. Comparing base (30607c4) to head (11f1024).

Files with missing lines Patch % Lines
src/sed/compiler.rs 0.00% 63 Missing ⚠️
src/sed/processor.rs 0.00% 49 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #481      +/-   ##
==========================================
- Coverage   83.05%   81.79%   -1.26%     
==========================================
  Files          13       13              
  Lines        6120     6214      +94     
  Branches      358      367       +9     
==========================================
  Hits         5083     5083              
- Misses       1034     1128      +94     
  Partials        3        3              
Flag Coverage Δ
macos_latest 82.46% <0.00%> (-1.31%) ⬇️
ubuntu_latest 82.56% <0.00%> (-1.29%) ⬇️
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.

@PranavRJoshi

Copy link
Copy Markdown
Contributor Author

Seems like CRLF issue on Windows. Will make those tests conditionally compile on UNIX only.

@dspinellis dspinellis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for the quick turnaround and thorough testing! I added a few improvement suggestions.

Comment thread src/sed/processor.rs
let mut child = shell_command(cmd)
.stdout(std::process::Stdio::piped())
.spawn()?;
let mut stdout = child.stdout.take().expect("stdout was piped");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Better: "stdout should be piped"

Comment thread src/sed/processor.rs
.unwrap_err()
})?;
let mut shell_out = String::from_utf8_lossy(&stdout_bytes).into_owned();
if shell_out.ends_with("\r\n") {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Make this active only for #[cfg(windows)]. I wanted to comment on the previous PR, but let it pass to move ahead.

Comment thread src/sed/processor.rs
if shell_out.ends_with("\r\n") {
// On windows, both return carriage and newline characters are used
shell_out.truncate(shell_out.len() - 2);
} else if shell_out.ends_with('\n') {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

But keep this also for Windows, because some Windows tools use \n.

Comment thread src/sed/processor.rs
)
.unwrap_err()
})?;
let mut shell_out = String::from_utf8_lossy(&stdout_bytes).into_owned();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As sed is a data processing tool rather than a UI front-end, we should avoid from_utf8_lossy, which can lead to silent data corruption. I suggest using (through a suitable method) IOChunk::from_content.

Comment thread src/sed/processor.rs
shell_out.pop();
}
pattern.set_to_string(shell_out, pattern.is_newline_terminated());
execute_pattern_as_shell(pattern, command, context)?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Great reuse!

Comment thread src/sed/processor.rs

/// Execute the pattern space as a shell command, replacing its contents
/// with the command's standard output, minus one trailing newline.
fn execute_pattern_as_shell(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Better names execute_pattern_through_shell or execute_pattern_as_shell_command .

Comment thread src/sed/processor.rs
)
.unwrap_err()
})?;
output.write_str(String::from_utf8_lossy(&stdout_bytes).into_owned())?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please avoid from_utf8_lossy

Comment thread tests/by-util/test_sed.rs

////////////////////////////////////////////////////////////
// e command (execute)
#[cfg(unix)]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add a separate corresponding test for Windows.

@PranavRJoshi

Copy link
Copy Markdown
Contributor Author

Appreciate the thorough review. Will make the appropriate changes and commit them later.

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.

Add e command (execute)

2 participants