On 2026-07-02 12:57, Borden via Bug reports for GNU grep wrote:

I've avoided sed and awk because I don't want to learn a different regex syntax 
when it's just faster for me to plug everything into Python instead.

Depends on whether you want fast development (where Python excels) or fast performance (where GNU grep runs rings around Python). Your choice, of course.

May as well close this pull request. I'm sorry for wasting your time and 
bandwidth.

It wasn't a waste at all. It's helpful to get fresh eyes to look at the documentation, and your comments exposed a real deficiency. Thank you.

The consensus seems to be that the grep man page should defer to regexp(7), and this seems good to me as well: it lessens the burden on the reader (why should there be duplicate documentation for regexps in the manual?) and on maintenance.

So I installed the attached patches to try to do this. The first changes grep's man page to defer to regexp(7) and to document only the places where GNU grep differs from standard POSIX. The second changes the documentation to fix some glitches I noticed when updating the man page (this is part of that maintenance duplication of effort, alas).

Boldly closing the bug report; we can reopen it if there are still problems.
From 4ea4b0ab24eedccbb104cf07a3b1f070b5749ef8 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Tue, 7 Jul 2026 11:26:55 -0700
Subject: [PATCH 1/2] doc: omit regex duplication from man page
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Inspired by a bug report by Borden (bug#81341).
* doc/grep.in.1: Do not attempt to document BREs and EREs in
detail, as that’s the job of regexp(7), just as documenting PCREs
is the job of pcre2pattern(3).  Just document GNU extensions.
This helps avoid duplication in the manual that complicates the
reader’s job and increases maintenance effort.  Come to think of
it, pcre2pattern(3) is the only PCRE man page we need to cite, so
do that too.
---
 doc/grep.in.1 | 267 +++++++++++++++-----------------------------------
 1 file changed, 80 insertions(+), 187 deletions(-)

diff --git a/doc/grep.in.1 b/doc/grep.in.1
index 0a04be4..9789c64 100644
--- a/doc/grep.in.1
+++ b/doc/grep.in.1
@@ -761,119 +761,36 @@ expressions, by using various operators to combine smaller expressions.
 .B grep
 understands three different versions of regular expression syntax:
 \*(lqbasic\*(rq (BRE), \*(lqextended\*(rq (ERE) and \*(lqperl\*(rq (PCRE).
-In GNU
-.BR grep ,
-basic and extended regular expressions are merely different notations
-for the same pattern-matching functionality.
-In other implementations, basic regular expressions are ordinarily
-less powerful than extended, though occasionally it is the other way around.
-The following description applies to extended regular expressions;
-differences for basic regular expressions are summarized afterwards.
-Perl-compatible regular expressions have different functionality, and are
+Basic and extended regular expressions are documented in
+.BR regex (7).
+Perl-compatible regular expressions are
 documented in
-.BR pcre2syntax (3)
-and
 .BR pcre2pattern (3),
 but work only if PCRE support is enabled.
 .PP
-The fundamental building blocks are the regular expressions
-that match a single character.
-Most characters, including all letters and digits,
-are regular expressions that match themselves.
-Any meta-character with special meaning
-may be quoted by preceding it with a backslash.
-.PP
-The period
-.B .\&
-matches any single character.
-It is unspecified whether it matches an encoding error.
-.SS "Character Classes and Bracket Expressions"
-A
-.I "bracket expression"
-is a list of characters enclosed by
-.B [
-and
-.BR ] .
-It matches any single
-character in that list.
-If the first character of the list
-is the caret
-.B ^
-then it matches any character
-.I not
-in the list; it is unspecified whether it matches an encoding error.
-For example, the regular expression
-.B [0123456789]
-matches any single digit.
-.PP
-Within a bracket expression, a
-.I "range expression"
-consists of two characters separated by a hyphen.
-In the default C locale, it matches any single character that appears
-between the two characters in ASCII order, inclusive.
-For example,
-.B [a\-d]
-is equivalent to
-.BR [abcd] .
-In other locales the behavior is unspecified:
-.B [a\-d]
-might be equivalent to
-.B [abcd]
-or
-.B [aBbCcDd]
-or some other bracket expression,
-or it might fail to match any character, or the set of
-characters that it matches might be erratic, or it might be invalid.
-To obtain the traditional interpretation of bracket expressions,
-you can use the C locale by setting the
-.B LC_ALL
-environment variable to the value
-.BR C .
-.PP
-Finally, certain named classes of characters are predefined within
-bracket expressions, as follows.
-Their names are self explanatory, and they are
-.BR [:alnum:] ,
-.BR [:alpha:] ,
-.BR [:blank:] ,
-.BR [:cntrl:] ,
-.BR [:digit:] ,
-.BR [:graph:] ,
-.BR [:lower:] ,
-.BR [:print:] ,
-.BR [:punct:] ,
-.BR [:space:] ,
-.BR [:upper:] ,
+The rest of this section documents
+several GNU extensions to portable, standard POSIX BREs and EREs,
+and clarifies GNU
+.BR grep 's
+behavior in areas where the POSIX standard leaves things undefined.
+.SS "BREs and EREs Have the Same Power"
+GNU BREs and EREs  are merely different notations
+for the same pattern-matching functionality.
+In other implementations, BREs are ordinarily
+less powerful than EREs, though occasionally it is the other way around.
+To support this, GNU BREs can use the escape sequences
+.BR \e? ,
+.BR \e+ ,
 and
-.BR [:xdigit:] .
-For example,
-.B [[:alnum:]]
-means the character class of numbers and
-letters in the current locale.
-In the C locale and ASCII
-character set encoding, this is the same as
-.BR [0\-9A\-Za\-z] .
-(Note that the brackets in these class names are part of the symbolic
-names, and must be included in addition to the brackets delimiting
-the bracket expression.)
-Most meta-characters lose their special meaning inside bracket expressions.
-To include a literal
-.B ]
-place it first in the list.
-Similarly, to include a literal
-.B ^
-place it anywhere but first.
-Finally, to include a literal
-.B \-
-place it last.
-.SS Anchoring
-The caret
-.B ^
-and the dollar sign
-.B $
-are meta-characters that respectively match the empty string at the
-beginning and end of a line.
-.SS "The Backslash Character and Special Expressions"
+.BR \e| ,
+with the same meaning as their unescaped ERE counterparts,
+and GNU EREs can use back-references
+.BI \e n
+with the same meaning as in BREs.
+.SS "Other Backslash Escapes"
+GNU
+.B grep
+supports several other backslash escapes beyond what POSIX requires.
 The symbols
 .B \e<
 and
@@ -895,84 +812,62 @@ and
 .B \eW
 is a synonym for
 .BR [^_[:alnum:]] .
-.SS Repetition
-A regular expression may be followed by one of several repetition operators:
-.PD 0
-.TP
-.B ?
-The preceding item is optional and matched at most once.
-.TP
-.B *
-The preceding item will be matched zero or more times.
-.TP
-.B +
-The preceding item will be matched one or more times.
-.TP
-.BI { n }
-The preceding item is matched exactly
-.I n
-times.
-.TP
-.BI { n ,}
-The preceding item is matched
-.I n
-or more times.
-.TP
-.BI {, m }
-The preceding item is matched at most
-.I m
-times.
-This is a GNU extension.
-.TP
-.BI { n , m }
-The preceding item is matched at least
-.I n
-times, but not more than
-.I m
-times.
-.PD
-.SS Concatenation
-Two regular expressions may be concatenated; the resulting
-regular expression matches any string formed by concatenating
-two substrings that respectively match the concatenated
-expressions.
-.SS Alternation
-Two regular expressions may be joined by the infix operator
-.BR | ;
-the resulting regular expression matches any string matching
-either alternate expression.
-.SS Precedence
-Repetition takes precedence over concatenation, which in turn
-takes precedence over alternation.
-A whole expression may be enclosed in parentheses
-to override these precedence rules and form a subexpression.
-.SS "Back-references and Subexpressions"
-The back-reference
-.BI \e n\c
-\&, where
-.I n
-is a single digit, matches the substring
-previously matched by the
-.IR n th
-parenthesized subexpression of the regular expression.
-.SS "Basic vs Extended Regular Expressions"
-In basic regular expressions the meta-characters
-.BR ? ,
-.BR + ,
-.BR { ,
-.BR | ,
-.BR ( ,
-and
-.B )
-lose their special meaning; instead use the backslashed
-versions
-.BR \e? ,
-.BR \e+ ,
-.BR \e{ ,
-.BR \e| ,
-.BR \e( ,
+.SS "Effects of Encoding Errors"
+It is unspecified whether the pattern
+.B .\&
+matches an encoding error.
+It is also unspecified whether a non-matching list expression
+(i.e., a bracket expression whose first character is
+.BR ^ )
+matches an encoding error.
+This means GNU
+.B grep
+might match, or might not, but will not crash.
+In other implementations,
+.B grep
+might crash when given encoding errors in either patterns or data.
+.SS "Character Classes and Bracket Expressions"
+In locales other than the default C locale, the set of characters
+matched by a range expression is unspecified:
+.B [a\-d]
+might be equivalent to
+.B [abcd]
+or
+.B [aBbCcDd]
+or some other bracket expression,
+or it might fail to match any character, or the set of
+characters that it matches might be erratic, or it might be invalid.
+To obtain the traditional interpretation of bracket expressions,
+you can use the C locale by setting the
+.B LC_ALL
+environment variable to the value
+.BR C .
+.SS Empty Regular Expressions
+GNU BREs and EREs allow empty regular expressions, either
+at the top level, or as alternatives in subexpressions.
+.SS "Anchoring in BREs"
+In BREs, the caret
+.B ^
+acts as an anchor when it immediately follows
+.B \e(
+or
+.B \e|
+in a subexpression, and the dollar sign
+.B $
+acts as an anchor when it immediately precedes
+.B \e)
+or
+.B \e|
+in a subexpression.
+Other
+.B grep
+implementations may treat these patterns as ordinary characters
+in these contexts, even if they support
+.BR \e(,
+.BR \e|,
 and
-.BR \e) .
+.B \e)
+in BREs.
 .
 .SH "EXIT STATUS"
 Normally the exit status is 0 if a line is selected, 1 if no lines
@@ -1330,8 +1225,6 @@ from the globbing syntax that the shell uses to match file names.
 .BR sort (1),
 .BR xargs (1),
 .BR read (2),
-.BR pcre2 (3),
-.BR pcre2syntax (3),
 .BR pcre2pattern (3),
 .BR terminfo (5),
 .BR glob (7),
-- 
2.53.0

From af1768282907071ee0b8cb9ab0eef1010cbbd4d1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Tue, 7 Jul 2026 11:28:54 -0700
Subject: [PATCH 2/2] doc: update for POSIX.1-2024 \|
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* doc/grep.texi (Fundamental Structure): Document that empty EREs
can be followed by a repetition operator only when at the start of
a regular expression or subexpression.
(Problematic Expressions): Adjust to POSIX.1-2024’s semi-blessing
of \| in BREs.
---
 doc/grep.texi | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/doc/grep.texi b/doc/grep.texi
index 1a92931..d5d4026 100644
--- a/doc/grep.texi
+++ b/doc/grep.texi
@@ -1336,6 +1336,11 @@ The preceding item is matched at least @var{n} times, but not more than
 @end table
 
 The empty regular expression matches the empty string.
+This is a GNU extension.
+However, the empty regular expression can be followed by a repetition operator
+only if it immediately follows @samp{(} or @samp{|} or is at the start
+of the overall regular expression.
+
 Two regular expressions may be concatenated;
 the resulting regular expression
 matches any string formed by concatenating two substrings
@@ -1729,6 +1734,8 @@ Special backslash expressions like @samp{\b}, @samp{\<}, and @samp{\]}.
 
 @item
 A basic regular expression that uses @samp{\?}, @samp{\+}, or @samp{\|}.
+POSIX allows an implementation to define whether these act as in GNU
+@command{grep}, or merely match the corresponding literal characters.
 
 @item
 An extended regular expression that uses back-references.
@@ -1740,8 +1747,8 @@ example, @samp{(a|bc|)} is not portable; a portable equivalent is
 
 @item
 In a basic regular expression, an anchoring @samp{^} that appears
-directly after @samp{\(}, or an anchoring @samp{$} that appears
-directly before @samp{\)}.
+directly after @samp{\(} or @samp{\|}, or an anchoring @samp{$} that appears
+directly before @samp{\)} or @samp{\|}.
 
 @item
 In a basic regular expression, a repetition operator that
-- 
2.53.0

Reply via email to