Skip to content

^ in an alternation group silently fails to match (e.g. (a|b|^)x, (^|[^0-9])x), while GNU grep matches #573

Description

@gorloffslava

ugrep 7.8.5 (the v7.8.5 tag built from source, ./configure && make, gcc 14, aarch64 Linux) returns no match for some
regexes whose group has ^ as one alternative, where GNU grep 3.x matches. There is no error or warning; the count is
just wrong. The $ anchor in the same positions works.

Reproduction:

printf 'fail 1\nx; fail 2\nfoo\n' > input.txt
printf '5798-72bbf60eb5b8.json\n' > input2.txt

ugrep -cE '(^|a|b)fail' input.txt      # 1  (GNU grep: 1)
ugrep -cE '(a|^|b)fail' input.txt      # 1  (GNU grep: 1)
ugrep -cE '(a|b|^)fail' input.txt      # 0  (GNU grep: 1)   <- ^ as the third alternative
ugrep -cE '(a|b|c|^)fail' input.txt    # 0  (GNU grep: 1)
ugrep -cE '(a|b|^|c)fail' input.txt    # 0  (GNU grep: 1)
ugrep -cE '(;|&&|^)fail' input.txt     # 0  (GNU grep: 1)

ugrep -cE '(^|x)5798' input2.txt       # 1  (GNU grep: 1)
ugrep -cE '(^|[^0-9])5798' input2.txt  # 0  (GNU grep: 1)   <- ^ first, but the other alternative is a bracket class
ugrep -cE '([^0-9]|^)5798' input2.txt  # 0  (GNU grep: 1)

printf 'x fail\nfail\n' > input3.txt
ugrep -cE 'fail(a|b|$)' input3.txt     # 2  (GNU grep: 2)   <- $ is fine in every position tried

The same results come from ugrep 7.8.4. As far as I can tell, ^ placed third or later in a group never matches, and
^ in first or second place fails when another alternative is a bracket expression. In both cases the line-start
alternative is dropped with no diagnostic.

Why it matters: patterns like (^|[^0-9])N([^0-9]|$) and (^|;|&&)cmd are common idioms for "N as a whole token" and
"cmd at the start of a statement". With ugrep they silently undercount. We found it because a count we had recorded was
wrong for weeks: it was always taken with ugrep and was off by exactly the line-initial matches.

Expected: the same matches as GNU grep (POSIX ERE: ^ is an anchor in any alternative), or an error like the one #427
used to raise, rather than a silent miss.

(Found while auditing shell commands an AI coding assistant had run; the reproduction above was checked by hand
against standalone builds of ugrep and GNU grep.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions