From 2a5610be455a966457111aa79a0e77c782dd53aa Mon Sep 17 00:00:00 2001 From: Wondr Date: Fri, 5 Jun 2026 11:45:49 +0100 Subject: [PATCH 1/2] grep: honor GNU buffer anchors --- src/matcher.rs | 4 ++++ tests/test_grep.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/matcher.rs b/src/matcher.rs index 783d239..6da6d9b 100644 --- a/src/matcher.rs +++ b/src/matcher.rs @@ -269,6 +269,10 @@ impl CompiledPattern { // GNU grep supports `{,n}` as an alias for `{0,n}`. syntax.enable_behavior(SyntaxBehavior::SYNTAX_BEHAVIOR_ALLOW_INTERVAL_LOW_ABBREV); } + if matches!(config.regex_mode, RegexMode::Basic | RegexMode::Extended) { + // GNU grep supports \` and \' as buffer anchors in BRE and ERE. + syntax.enable_operators(SyntaxOperator::SYNTAX_OPERATOR_ESC_GNU_BUF_ANCHOR); + } if config.regex_mode == RegexMode::Perl { // GNU grep supports `(?P...)`. // Unfortunately, the onig crate defines the OP2 flag without the diff --git a/tests/test_grep.rs b/tests/test_grep.rs index fbea0a0..d190d98 100644 --- a/tests/test_grep.rs +++ b/tests/test_grep.rs @@ -85,6 +85,33 @@ fn bre_gnu_extensions() { .stdout_only("*foo\n**foo\n"); } +#[test] +fn gnu_buffer_anchors() { + let (_s, mut c) = ucmd(); + c.args(&[r"\`c"]) + .pipe_in("cat\nscat\ndog\n") + .succeeds() + .stdout_only("cat\n"); + + let (_s, mut c) = ucmd(); + c.args(&[r"t\'"]) + .pipe_in("cat\ntar\ndog\n") + .succeeds() + .stdout_only("cat\n"); + + let (_s, mut c) = ucmd(); + c.args(&["-E", r"\`c"]) + .pipe_in("cat\nscat\ndog\n") + .succeeds() + .stdout_only("cat\n"); + + let (_s, mut c) = ucmd(); + c.args(&["-E", r"t\'"]) + .pipe_in("cat\ntar\ndog\n") + .succeeds() + .stdout_only("cat\n"); +} + #[test] fn ere_metacharacters() { let cases: &[(&[&str], &str, &str)] = &[ From 0ec43c8f68dab26bc67e2085627ff0fee7f65603 Mon Sep 17 00:00:00 2001 From: Wondr Date: Fri, 5 Jun 2026 15:44:20 +0100 Subject: [PATCH 2/2] grep: compact buffer anchor tests --- tests/test_grep.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/tests/test_grep.rs b/tests/test_grep.rs index d190d98..6a42175 100644 --- a/tests/test_grep.rs +++ b/tests/test_grep.rs @@ -88,28 +88,16 @@ fn bre_gnu_extensions() { #[test] fn gnu_buffer_anchors() { let (_s, mut c) = ucmd(); - c.args(&[r"\`c"]) - .pipe_in("cat\nscat\ndog\n") + c.args(&[r"\`c\|r\'"]) + .pipe_in("cat\nscat\ntar\ndog\n") .succeeds() - .stdout_only("cat\n"); + .stdout_only("cat\ntar\n"); let (_s, mut c) = ucmd(); - c.args(&[r"t\'"]) - .pipe_in("cat\ntar\ndog\n") + c.args(&["-E", r"\`c|r\'"]) + .pipe_in("cat\nscat\ntar\ndog\n") .succeeds() - .stdout_only("cat\n"); - - let (_s, mut c) = ucmd(); - c.args(&["-E", r"\`c"]) - .pipe_in("cat\nscat\ndog\n") - .succeeds() - .stdout_only("cat\n"); - - let (_s, mut c) = ucmd(); - c.args(&["-E", r"t\'"]) - .pipe_in("cat\ntar\ndog\n") - .succeeds() - .stdout_only("cat\n"); + .stdout_only("cat\ntar\n"); } #[test]