Skip to content

Commit 2933286

Browse files
committed
expr: Handle special cases for $ in regex
Enable fixed test `test_bre11`
1 parent f664578 commit 2933286

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

src/uu/expr/src/syntax_tree.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl StringOp {
156156
re_string.push('^');
157157

158158
// Handle first character from the input pattern
159-
let mut pattern_chars = right.chars();
159+
let mut pattern_chars = right.chars().peekable();
160160
let first = pattern_chars.next();
161161
match first {
162162
Some('^') => {} // Start of string anchor is already added
@@ -166,10 +166,9 @@ impl StringOp {
166166
};
167167

168168
// Handle the rest of the input pattern.
169-
// Escaped previous character should not affect the current.
170169
let mut prev = first.unwrap_or_default();
171170
let mut prev_is_escaped = false;
172-
for curr in pattern_chars {
171+
while let Some(curr) = pattern_chars.next() {
173172
match curr {
174173
'^' => match (prev, prev_is_escaped) {
175174
// Start of a capturing group
@@ -181,6 +180,26 @@ impl StringOp {
181180
// Explicitly escaped caret
182181
| ('\\', false) => re_string.push(curr),
183182
_ => re_string.push_str(r"\^"),
183+
},
184+
'$' => {
185+
if let Some('\\') = pattern_chars.peek() {
186+
// The next character was checked to be a backslash
187+
let backslash = pattern_chars.next().unwrap_or_default();
188+
match pattern_chars.peek() {
189+
// End of a capturing group
190+
Some(')') => re_string.push('$'),
191+
// End of an alternative pattern
192+
Some('|') => re_string.push('$'),
193+
_ => re_string.push_str(r"\$"),
194+
}
195+
re_string.push(backslash);
196+
} else if (prev_is_escaped || prev != '\\')
197+
&& pattern_chars.peek().is_some()
198+
{
199+
re_string.push_str(r"\$");
200+
} else {
201+
re_string.push('$');
202+
}
184203
}
185204
_ => re_string.push(curr),
186205
}

tests/by-util/test_expr.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ fn test_regex() {
294294
.args(&["a$b", ":", "a\\$b"])
295295
.succeeds()
296296
.stdout_only("3\n");
297+
new_ucmd!()
298+
.args(&["a", ":", "a$\\|b"])
299+
.succeeds()
300+
.stdout_only("1\n");
301+
new_ucmd!()
302+
.args(&["ab", ":", "a\\(b$\\)"])
303+
.succeeds()
304+
.stdout_only("b\n");
297305
new_ucmd!()
298306
.args(&["abc", ":", "^abc"])
299307
.succeeds()
@@ -306,6 +314,10 @@ fn test_regex() {
306314
.args(&["b^$ic", ":", "b^\\$ic"])
307315
.succeeds()
308316
.stdout_only("5\n");
317+
new_ucmd!()
318+
.args(&["a$c", ":", "a$\\c"])
319+
.succeeds()
320+
.stdout_only("3\n");
309321
new_ucmd!()
310322
.args(&["^^^^^^^^^", ":", "^^^"])
311323
.succeeds()
@@ -774,7 +786,6 @@ mod gnu_expr {
774786
.stdout_only("3\n");
775787
}
776788

777-
#[ignore]
778789
#[test]
779790
fn test_bre11() {
780791
new_ucmd!()

0 commit comments

Comments
 (0)