Why is non-greedy match consuming entire pattern even when followed by another non-greedy match

Using PHP8, I’m struggling to figure out how to conditionally match some key that may or may not appear in a string.
I would like to match both

-----------key=xyz---------------

AND

--------------------------

The dashes("-") could be any non-space character, and only used here for a cleaner to read example.

The regex is matching "key=…" if its containing group is greedy like below.
But this isn’t adequate, because the full match will fail a "key=xyz" is missing the subject string.

/
(\S*)?                 
(key\=(?<foundkey>[[:alnum:]-]*))
\S*
/x

if that capture group is non-greedy, then the regex just ignores the key match any "key=xyz"

/
(\S*)?                 
(key\=(?<foundkey>[[:alnum:]-]*))?
\S*
/x

I tried debugging in this regex101 example but couldn’t figure it out.

I sorted this out using multiple regexs, but hoping someone can help address my misunderstandings so I learn know how to make this work as a single regex.
Thanks

>Solution :

You may use:

/
^
\S*?
(?:
   key=(?<foundkey>\w+)
   \S*
)?
$
/xm

RegEx Demo

RegEx Breakdown:

  • ^: Start
  • \S*?: Match 0 or more whitespaces non-greedy
  • (?:: Start Lookahead
    • key=(?<foundkey>\w+): Match key= text followed by 1+ word characters as capture group foundkey
    • \S*: Match 0 or more whitespaces
  • )?: End lookahead. ? makes it an optional match
  • $; End

Leave a Reply