4

I want 3 capturing groups (pre/mid/post) that share some characters. All three can match 0 or 1 time, something like this:

^(?<pre>[T])?(?<mid>[T][A-Z])?(?<post>[T])?$

I am looking for them to match in order: mid -> pre -> post. Regex I've posted works for 3/4 letter strings, like TTT / TTU / TUT. For two character string TT, I would like for group mid to be matched - the result is pre: T, post: T though. I understand why that's happening - pre matches, mid doesn't find two character to match, post matches.

For mid to take precedence I've tried combinations of groups and lazy operators, but most of them resulted in post matching before pre, like for this example:

^(?<pre>[T])??(?<mid>[T][A-Z])?(?<post>[T])?$

Is there any way to allow mid group to match before pre? Can you set some kind of order of matching?

knittl
  • 246,190
  • 53
  • 318
  • 364
rybaczewa
  • 43
  • 3
  • 1
    To match `mid` before `pre`, you are using the lazy `??` correctly. What is wrong with [`^(?
    T)??(?T[A-Z])?(?T)?$`](https://regex101.com/r/XkBUYQ/1)?
    – Wiktor Stribiżew May 18 '22 at 17:47
  • `TTT` matches as `mid + post`, whereas I would like it to match `pre + mid`. With both prefix and suffix having `??` operator, suffix matches first. Only the last lazy operator matches. I couldn't figure out a way to kind of keep the lazy operator within group. Like `((pre)(mid))(post)` – rybaczewa May 18 '22 at 21:48
  • [`^(?
    T)?(?T[A-Z])?(?T)?$`](https://regex101.com/r/XkBUYQ/2) gives the expected `pre+mid`.
    – Wiktor Stribiżew May 18 '22 at 21:53
  • 2
    @WiktorStribiżew But that no longer matches `TT` with only `mid`, like your first attempt did – Bergi May 18 '22 at 22:07

1 Answers1

2

I don't think you need any lazy operators - just explicitly group pre together with mid, so that if pre matches then mid is required:

^(?:(?<pre>T)?(?<mid>T[A-Z]))?(?<post>T)?$

(online demo)

Or rather, I think you want to require mid to match together with an optional post, so that a single T input is matched by pre only:

^(?<pre>T)?(?:(?<mid>T[A-Z])(?<post>T)?)?$

(online demo)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • The second one is what I was looking for. Seems like I was unnecessarily exploring lazy operators and non-capturing groups were the way. Thanks! – rybaczewa May 19 '22 at 06:38