1

I'm new to writing Regex patterns and I'm struggling to understand why the following line doesn't work.

/^(£)?[0-9]+(?(?=\.[0-9]{2}){0,1}(p)?|$)/

Note: I'm writing this in PHP

I want the code to find £3.10p, but not £3p. Essentially, the letter 'p' can't be allowed unless it is preceded with a decimal point and 2 digits.

EDIT: To clarify, the letter p can be used at the end of the string, however if the string contains a £ and/or a decimal point, the p must be preceded by the point and 2 digits.

More examples of valid inputs: £3.50 350 £350 234p

Invalid input: £2p

Could someone please fix this and explain where I've gone wrong here?

Thanks

3
  • 1
    but p in this isn't preceed by decimal point 234p Commented Mar 10, 2015 at 12:15
  • @AvinashRaj Thanks for pointing that out, my bad. I've added an edit to the origin post. Commented Mar 10, 2015 at 12:54
  • @n-dru Yes I think that will be allowed. Commented Mar 10, 2015 at 12:54

4 Answers 4

1

If 0.50p is allowed, then you can do it like this:

^((£?[0-9]+)(?!p)|([0-9]+p?))?(?<!p)(\.[0-9]{2})?p?$

Regex saved with all your examples here: https://regex101.com/r/rE1bT9/3

Sign up to request clarification or add additional context in comments.

3 Comments

This works, thanks very much. As I said in my post, I'm new to Regex and still find it confusing. Would you mind explaining briefly what your pattern does that mine doesn't?
In first segment I contained that it is zero or one pound sign with at least one digit without trailing "p" OR at least one digit with "p" - this segment is one or zero times. Next is optional point with two digits and optional "p". But wait, I just found a bug. It allows now for 3p.50p. I am updating answer with correction!
Thanks for the fix. I tried to fix it myself but was unsuccessful :)
1

Try this: /^(?(?=£)(£\d+\.\d{2}p?|£\d+)|\d+p?)$/

You can test it here: https://regex101.com/r/mG8kR0/1

Comments

0

It is unclear how your valid sample "234p" matches your rule "p is allowed if there are at least two digits and a point". However, in your question you are using positive lookahead, this seems an overhead here.

Your rule for p may be written as: (\.[0-9]{2}p?)

So over all, you just need: /^(£)?[0-9]+(\.[0-9]{2}p?)$/

And if you allow "234p" also, just make the period optional: /^(£)?[0-9]+(\.?[0-9]{2}p?)$/

Try it out here: http://www.regexr.com/

The latter regex gives positive feedback to all your valid samples, and it denies the invalid input. It is unclear what should happen if there are only two digits, and if it is important to catch some pieces, there should be more brackets.

Comments

0

How about:

/^(?:£?[0-9]+(?:\.[0-9]{2})?|[0-9]+p?)$)/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.