Regex: Decimal with constraints and certain alpha characters allowed at the end

Viewed 79

Figure I'll put this here for posterity.

What is the regex for ####.@@@@X?

  • Where "#" is any number up to 4 digits before the decimal point but only one leading 0 allowed
  • Where "@" is any number up to 4 digits after the decimal point
  • Where "X" is a single alpha character in a given list (A or a, X or x) that must come last

Examples to pass:

  • .309x
  • 0.309
  • 1
  • 0.0
  • 1.0234
  • 0.2345X (IMPORTANT, should only allow one leading 0)
  • 1.23A
  • 7300.3211x
  • 0.1a

Examples to fail:

  • 01.123
  • 00.234
  • a.123
  • 1.23p
  • 00.43x

What I have now:

  • ^\d{1,4}(\.\d{0,4})?$
  • This works for 4 numbers before and after decimal
  • But doesn't account for the the single leading 0 NOR the alpha at the end.

EDIT 1:

  • Testing your solutions made me realize some other cases.
  • I updated the pass/fail scenarios
  • The biggest revelations are:
    • The leading number is optional
    • The decimal point is optional
    • The alpha character at the end is optional
    • A leading 0 should only be followed the decimal point.
      • e.g: 0.123 yes; 01.234 no

Answers:

  • @TheFourthBird and @AaronMorefield got it with these:
^(?!00|0[1-9]\.)(?:\d{0,4}\.\d{1,4}[aAxX]?|\d{1,4})$

((^[1-9])(\d{0,3})|^0|^)((\.?)\d{0,4})(|[A-Za-z])$

I'll be studying these!

5 Answers

You could use

^(?!00|0[1-9]\.)(?:\d{0,4}\.\d{1,4}[aAxX]?|\d{1,4})$
  • ^ Start of string
  • (?!00|0[1-9]\.) Negative lookahead to exclude matching 00 or 01-9. at the start
  • (?: Non capture group
    • \d{0,4}\.\d{1,4} Match 0-4 digits, a . and 1-4 digits
    • [aAxX]? Optionally match a or x lower and uppercase variants
    • | Or
    • \d{1,4} Match 1-4 digits
  • ) Close non capture group
  • $ End of string

Regex demo

Use

^(?!00)\d{1,4}(?:\.\d{1,4}[aAxX]?)?$

See proof. It also allows numbers without period.

Explanation

--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    00                       '00'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  \d{1,4}                  digits (0-9) (between 1 and 4 times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \.                       '.'
--------------------------------------------------------------------------------
    \d{1,4}                  digits (0-9) (between 1 and 4 times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    [aAxX]?                  any optional character of: 'a', 'A', 'x', 'X'
--------------------------------------------------------------------------------
  )?                       end of grouping
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

My attempt =)

^(?!.*\d{5}|0\d)\d{0,4}\.?\d{1,4}[aAxX]?$

See the online demo

I took your "single leading 0" as though you just wanted to allow for "0.1" but disallow "01.1". Therefor I added an alternation within a non-capturing group. I guess I might be wrong looking at the other answers.

This matches your set without using any calculated look-arounds:

((^[1-9])(\d{0,3})|^0|^)((\.?)\d{0,4})(|[A-Za-z])$

This checks that the beginning of the string is any number 1 through 9 with three optional numbers afterwards, or exactly one leading zero. Then the explicit full-stop with up to 4 digits after, then optionally any Alpha numeric character and the end-string anchor.

Check the link to this Regex here: https://regex101.com/r/mBzNuN/2

^(?:|0|[1-9]\d{0,3})(?:\.\d{1,4})?(?<!^)[AaXx]?$

  • (?:|0|[1-9]\d{0,3}) : Before decimal point: Nothing or 0 or any number up to 4 digits ...

  • (?:\.\d{1,4})? : Decimal part (Optional)

  • (?<!^) : (lookbehind) verifies that there is an integer and/or decimal part

  • [AaXx]? : The alpha character at the end is optional

Related