diff --git a/src/sed/compiler.rs b/src/sed/compiler.rs index bcfff315..722ecc6e 100644 --- a/src/sed/compiler.rs +++ b/src/sed/compiler.rs @@ -1223,6 +1223,9 @@ fn compile_text_command_posix( line.advance(); // Skip \. line.eat_spaces(); // Skip any whitespace at the end of \. if !line.eol() { + // POSIX (and Seventh Edition Unix sed) do not allow text after the + // `a\`/`c\`/`i\` command on the same line. Same-line text is a GNU + // extension, handled by compile_text_command_gnu in non-POSIX mode. return compilation_error( lines, line, @@ -2734,6 +2737,8 @@ mod tests { #[test] fn test_compile_text_command_posix_spaces_single_line() { + // Under --posix, `a \ ` skips the whitespace after `\`; the text comes + // from the following script line(s), not the same line. let mut chars = make_char_provider("a \\ "); let mut lines = make_line_provider(&["line1", "line2"]); let mut cmd = Command::default(); @@ -2893,8 +2898,10 @@ mod tests { } #[test] - fn test_compile_text_command_posix_with_trailing_chars() { - let mut chars = make_char_provider("a \\ foo"); + fn test_compile_text_command_posix_same_line_text() { + // Under --posix, text after `a\` on the same line is rejected (it is a + // GNU extension). Cf. dspinellis review on uutils/sed#451. + let mut chars = make_char_provider("a\\bar"); let mut lines = make_line_provider(&["line1", "line2"]); let mut cmd = Command::default(); let mut context = ProcessingContext { @@ -2905,7 +2912,23 @@ mod tests { let result = compile_text_command(&mut lines, &mut chars, &mut cmd, &mut context); assert!(result.is_err()); let err = result.unwrap_err().to_string(); - assert!(err.contains("extra characters after \\")); + assert!(err.contains("extra characters after")); + } + + #[test] + fn test_compile_text_command_posix_same_line_continuation() { + // Same-line text, even with a trailing `\` continuation, is rejected + // under --posix; only `a\` followed by a newline is valid. + let mut chars = make_char_provider("a\\bar\\"); + let mut lines = make_line_provider(&["baz", "next"]); + let mut cmd = Command::default(); + let mut context = ProcessingContext { + posix: true, + ..Default::default() + }; + + let result = compile_text_command(&mut lines, &mut chars, &mut cmd, &mut context); + assert!(result.is_err()); } // read_file_path diff --git a/tests/by-util/test_sed.rs b/tests/by-util/test_sed.rs index b31fed76..24854b02 100644 --- a/tests/by-util/test_sed.rs +++ b/tests/by-util/test_sed.rs @@ -631,6 +631,10 @@ extra ] ); +// Text supplied on the same line as `a\` (GNU accepts this in POSIX mode +// too; see issue #144). Runs under both --posix and GNU parsing. +check_output_posix!(text_append_same_line, ["-e", r"4a\extra", LINES1]); + check_output_posix!( text_insert_quit, [ diff --git a/tests/fixtures/sed/output/text_append_same_line b/tests/fixtures/sed/output/text_append_same_line new file mode 100644 index 00000000..932349a2 --- /dev/null +++ b/tests/fixtures/sed/output/text_append_same_line @@ -0,0 +1,15 @@ +l1_1 +l1_2 +l1_3 +l1_4 +extra +l1_5 +l1_6 +l1_7 +l1_8 +l1_9 +l1_10 +l1_11 +l1_12 +l1_13 +l1_14