Search code examples
phpregexcurrencyregex-lookarounds

regex riddle. want results: 'onetwothree', 'onetwo', 'twothree' but NOT 'two'. Positive lookahead maybe?. For currency extraction


confused with some basic regex logic. Using simple example:

(one)(two)(three)

I want regex to catch:

onetwothree
onetwo
   twothree

but NOT

   two

and catching in groups (one)(two)(three).

I know I can use positive lookahead on 'two' so that it is only preceded by 'one':

(one)?((?<=one)two)(three)? 

but then I cannot get the 'twothree' result

The real world need is for currency:

group one:   [$¥£€₹]
group two:   ((?:\d{1,10}[,. ])*\d{1,10})
group three: ( ?(?:[$¥£€₹]|AUD|USD|GBP|EURO?S?\b))

so I want to get these results:

$20,000 AUD
$20,000
 20,000 AUD

but NOT

 20,000

help appreciated!

PS need matches in groups (one)(two)(three) or (one)(two) or (two)(three).


Solution

  • Here's a pure regex response:

    (ONE)?TWO(?(1)(THREE)?|THREE)
    

    Using conditionals, you can check to see if the first group matched, and if it did, then you can make the last group mandatory.

    (ONE)?TWO(?(1)(THREE)?|THREE)
    ^     ^  ^^^^^   ^       ^
    1     2    3     4       5
    
    1: Try to match ONE. If you can't find it, no big deal.
    2: You absolutely must have TWO.
    3: If the first group DID match (ONE), then...
    4: ... Use the first result
    5: Otherwise use the second result
    

    With this, we just make the first result be optional, so if we match ONE, then THREE is optional. If we miss ONE, then THREE is mandatory.

    ONE
    TWO
    THREE
    ONETWO       // Matches! (e.g: $20,000)
    ONETHREE
    TWOTHREE     // Matches! (e.g: 20,000 AUD)
    ONETWOTHREE  // Matches! (e.g: $20,000 AUD)
    

    Try it online!

    Read more about conditional regex patterns in PHP here.