Skip to content

Commit f24ab62

Browse files
chaliyclaude
andauthored
fix(builtins): fix sed ampersand replacement and escape handling (#196)
## Summary - Fix `&` (ampersand) replacement using `${0}` format to avoid regex crate ambiguity - Add `\n` and `\t` escape handling in replacement strings - Unskip pattern range addressing tests (`/start/,/end/` and `/pat/,$`) ## Test plan - [x] All sed spec tests pass, 5 tests unskipped - [x] `cargo check` clean Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6b5719b commit f24ab62

2 files changed

Lines changed: 6 additions & 9 deletions

File tree

crates/bashkit/src/builtins/sed.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,10 @@ fn parse_sed_command(s: &str, extended_regex: bool) -> Result<(Option<Address>,
416416

417417
// Convert sed replacement syntax to regex replacement syntax
418418
// sed uses \1, \2, etc. and & for full match
419-
// regex crate uses $1, $2, etc. and $0 for full match
419+
// regex crate uses ${N} format to avoid ambiguity
420420
let replacement = replacement
421421
.replace("\\&", "\x00") // Temporarily escape literal &
422-
.replace('&', "$0")
422+
.replace('&', "${0}")
423423
.replace("\x00", "&");
424424

425425
// Use ${N} format instead of $N to avoid ambiguity with following chars
@@ -428,6 +428,9 @@ fn parse_sed_command(s: &str, extended_regex: bool) -> Result<(Option<Address>,
428428
.replace_all(&replacement, r"$${$1}")
429429
.to_string();
430430

431+
// Convert \n → newline, \t → tab in replacement
432+
let replacement = replacement.replace("\\n", "\n").replace("\\t", "\t");
433+
431434
// Parse nth occurrence from flags (e.g., "2" in s/a/b/2)
432435
let nth = flags
433436
.chars()

crates/bashkit/tests/spec_cases/sed/sed.test.sh

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ d
5959
### end
6060

6161
### sed_ampersand
62-
### skip: ampersand (&) in replacement not fully working
6362
# Ampersand replacement
6463
printf 'hello\n' | sed 's/hello/[&]/'
6564
### expect
@@ -211,7 +210,7 @@ bird
211210
### end
212211

213212
### sed_hold_h
214-
### skip: hold space (h) command not implemented
213+
### skip: hold space with grouped commands not implemented
215214
printf 'a\nb\n' | sed '1h; 2{x;p;x}'
216215
### expect
217216
a
@@ -338,7 +337,6 @@ heo
338337
### end
339338

340339
### sed_literal_newline
341-
### skip: literal newlines in replacement not implemented
342340
printf 'a b\n' | sed 's/ /\n/'
343341
### expect
344342
a
@@ -399,7 +397,6 @@ XXX
399397
### end
400398

401399
### sed_multiple_patterns
402-
### skip: pattern range addressing not implemented
403400
printf 'a\nb\nc\nd\n' | sed '/a/,/c/d'
404401
### expect
405402
d
@@ -431,7 +428,6 @@ c
431428
### end
432429

433430
### sed_delete_range_pattern
434-
### skip: pattern/$ range addressing not implemented
435431
printf 'a\nb\nc\nd\n' | sed '/b/,$d'
436432
### expect
437433
a
@@ -453,7 +449,6 @@ printf '' | sed 's/x/y/'
453449
### end
454450

455451
### sed_special_chars_in_replacement
456-
### skip: ampersand (&) in replacement not working
457452
printf 'hello\n' | sed 's/hello/a&b/'
458453
### expect
459454
ahellob
@@ -485,7 +480,6 @@ yes
485480
### end
486481

487482
### sed_pattern_range
488-
### skip: pattern ranges not implemented
489483
printf 'a\nstart\nb\nend\nc\n' | sed '/start/,/end/d'
490484
### expect
491485
a

0 commit comments

Comments
 (0)