Thursday, April 28, 2011

RegEx to match 123.45 and E123.4 and V12.34

I'm trying to create a RegEx that matches the 3 patterns listed above. I can somewhat create a working RegEx for any of those 3 but my problem is creating one that works with all 4 of those. The allowed values are below, where D is any digit and the '.' is never present as a trailing character (i.e. DDD. wouldn't be valid). Also the V and E refer to those specific characters.

  • ddd
  • ddd.d
  • ddd.dd
  • Vdd
  • Vdd.d
  • Vdd.dd
  • Eddd
  • Eddd.d

Everything else should be invalid, such as:

  • d
  • dd
  • V
  • Vd
  • Vdd. (trailing '.')
  • E
  • Ed
  • Edd

I'm not great with RegEx, but I could describe part of this pattern for the entries that start with V as the following:

V[0-9]{2,2}(\.[0-9]{1,2})?

I could write very similar statements for the all digit portion of entires and E prefix portion of entries. The problem is how to combine all 3 into a RegEx that doesn't make my head spin to read. What's a good RegEx to match all 3 patterns?

EDIT: I forgot to include the format Vdd.dd

From stackoverflow
  • (E\d|(V|\d))\d{2,2}(\.\d)?(?(2)\d?|)
    

    E with one digit, or V, or a single digit, followed by two digits, then the usual decimal stuff.

    E has to have three non decimal digits, V has to have 2, and digits by them selves have to have three.

    If the V or single digit match at the start (I.E. Not 'E') then an extra digit is allowed on the rear.

    quadelirus : E and V can only be followed by 1 digit past the decimal (at least it seems that way from the post). This allows for Eddd.dd
    Grant : Fixed it. Now Eddd.d is disallowed.
  • (\d{3}(\.\d{1,2})?)|(V\d{2}(\.\d{1,2})?)|(E\d{3}(\.\d)?)
    

    EDIT: Some explanation: I just matched all 3 different formats:

    \d{3}(\.\d{1,2})?
    

    says three digits optionally followed by a period matched with 1 or 2 digits.

    V\d{2}(\.\d{1,2})?
    

    says V followed by two digits with optional period and one or two digits

    E\d{3}(\.\d)?
    

    says three digits followed by an optional period with a single digit

    Then I just surrounded each with () and combined them all with | (or).

    Jared Updike : put four spaces on the line with the backslash to make it treat it as code instead of MarkDown
    James Cadd : this looks very close to what i need - i forgot to include Vdd.dd as i mention in the edited post but otherwise this looks great!
    quadelirus : Should be fixed for that case now.
    quadelirus : I was wrong. Now it is fixed--I had put \d){1,2} when I meant \d{1,2})
    quadelirus : BTW I think you can spend a lot of time really trying to boil down a regexp into one expression but often it suffices to cover the basic cases and or them together with |--and many times this is much easier to figure out what its doing down the road when you have to modify the code three months after not touching it.
    quadelirus : One more mistake on there-- for the second case add a ?
    quadelirus : Should be correct now.
  • Nothing wrong with having three different regular expressions, is there?

    \d{3}(.\d{1,2)?
    V\d{2}(.\d)?
    E\d{3}(.\d)?
    

    And this will probably be more maintainable in the future.

    James Cadd : i'm using the regex for the mask field of devexpress silverlight controls toolkit, it only accepts a single string. but yes, otherwise i'd like to keep them separate.
  • If Eddd would be invalid it would be much easier:

    [EV\d]\d{2}(\.\d{0,2})?
    

    Similarly if Vddd was valid:

    [EV\d]\d{2,3}(\.\d{0,2})?
    

    Matching exactly what you have is a bit harder:

    (\d{3}(\.\d{1,2})?)|(V\d{2}(\.\d)?)|(E\d{3}(\.\d)?)
    

    Make sure you test for exact match otherwise things like

    V123.1
    

    Will match as

    V12
    
    James Cadd : Thank you for the explanation, it's very helpful. Yes if those strange cases didn't exist my life would be a bit easier ;)
    James Cadd : Had to edit slightly for my extra case that i forgot but this one completely works. ty. (\d{3}(\.\d{1,2})?)|(V\d{2}(\.\d{1,2})?)|(E\d{3}(\.\d)?)

0 comments:

Post a Comment