Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match an expression with at least a prefix and/or a postfix without repeating the expressions

Let's say

((pre)(expr)(post)?|(pre)?(expr)(post))

This is meant to match expr with at least a prefix or a postfix or both but not with neither.

preexpr - OK
exprpost - OK
preexprpost - OK
expr - BAD

This example is using letters, but all three sub-expressions could be any valid regex, not just letters.

Is there a way of writing an equivalent regex with each expression appearing only once? I'm trying to improve readability.

Right now I know I can remove the second occurrence of pre:

((pre)(expr)(post)?|(expr)(post))

but I'm wondering if it can still be reduced.

Thank you

like image 762
gxtaillon Avatar asked Dec 08 '25 08:12

gxtaillon


1 Answers

YES - This is what conditional constructs (?(n)yes regex|no regex) are made for.

In my opinion, the only value for conditionals are to pass or fail
the match based on something that did or did not match.

In this case, the below regex is checking if either optional groups 1 or 3 matched.
In reality, 'pre' and 'post' can be humungous sub-expressions
(but be careful of backtracking pitfalls).

This saves duplicity of sub-expressions.

https://regex101.com/r/QdhRn2/1

(pre)?(expr)(post)?(?(1)|(?(3)|(?!)))

Explained

 ( pre )?                      # (1), Optional 'pre'
 ( expr )                      # (2), Required 'exp'
 ( post )?                     # (3), Optional 'post'
                               # Post mortum
 (?(1)                         # Did group 1 match ?
   |  (?(3)                         # No, then did group 3 match ?
        |  (?!)                          # No.  Fail the whole thing
      )
 )
 # Here, at least group 1 or 3 matched, possibly both

Explained Verbose

 ( pre )?                      # (1), Optional 'pre'
 ( expr )                      # (2), Required 'exp'
 ( post )?                     # (3), Optional 'post'
                               # Post mortum
 (?(1)                         # Did group 1 match ?
                                    # Yes, all done
   |                              # or,
      (?(3)                         # No, then did group 3 match ?
                                         # Yes, all done
        |                              # or,
           (?!)                          # No.  Fail the whole thing
      )
 )
 # Here, at least group 1 or 3 matched, possibly both

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!