grep: select zero-width matches under -w and -x

This commit is contained in:
Wondr
2026-06-05 04:39:22 +01:00
parent f4798cb6d0
commit ad7595ffe6
2 changed files with 22 additions and 7 deletions
+10 -7
View File
@@ -28,13 +28,10 @@ impl<'a> Matcher<'a> {
/// Decide whether `line` matches and return the positions to highlight.
pub fn match_line(&self, line: &[u8]) -> Option<Vec<(usize, usize)>> {
let mut any_seen = false;
let mut any_selected = false;
let positions: Vec<_> = MatchIter::new(&self.patterns, line)
.filter(|&(start, end)| {
any_seen = true;
// Drop zero-length matches from the output.
if start == end {
return false;
}
// Drop matches that don't span the whole line if `-x` was requested.
if self.config.line_regexp && !(start == 0 && end == line.len()) {
return false;
@@ -43,13 +40,19 @@ impl<'a> Matcher<'a> {
if self.config.word_regexp && !Self::is_word_match(line, start, end) {
return false;
}
any_selected = true;
// Drop zero-length matches from the output.
if start == end {
return false;
}
true
})
.collect();
let raw_matched = if self.config.line_regexp || self.config.word_regexp {
// -w / -x are authoritative once positions are filtered.
!positions.is_empty()
// -w / -x are authoritative once matches are filtered. Zero-length
// matches can select a line even though there is no span to output.
any_selected
} else {
any_seen
};
@@ -174,7 +177,7 @@ struct Cursor<'a> {
impl Cursor<'_> {
fn refill(&mut self) {
if self.offset >= self.line.len() {
if self.offset > self.line.len() {
self.pending = None;
return;
}
+12
View File
@@ -251,6 +251,12 @@ fn word_regexp() {
.pipe_in("foo bar\nfoobar\n")
.succeeds()
.stdout_only("foo bar\n");
let (_s, mut c) = ucmd();
c.args(&["-w", "$"])
.pipe_in("abc\n\nx\n")
.succeeds()
.stdout_only("\n");
}
#[test]
@@ -260,6 +266,12 @@ fn line_regexp() {
.pipe_in("foo bar\nfoo bar!\nx foo bar\n")
.succeeds()
.stdout_only("foo bar\n");
let (_s, mut c) = ucmd();
c.args(&["-x", "$"])
.pipe_in("abc\n\nx\n")
.succeeds()
.stdout_only("\n");
}
#[test]