How can I create a regex that allows whole numbers, decimals, fractions, and fractions with decimals? The string can also have optional text, only at the end. So far I have this:
const re = /^d*.?d*/?d*.?d*[a-z]*$/gi;
This allows double decimals in a whole number(ie: ‘23.23.23’), which I do not want. Can I modify this regex to allow two decimal points only if it is separated by a ‘/’?
Here are some examples that can pass:
- 23.23/100km
- 1/3
- .23km
- 1.mi
- 1.2/2.1kg
Some examples that shouldn’t pass:
- 1a3km
- 12.12.12
- 1.2.3/12.13km
- 12km/12.44km
Advertisement
Answer
Use
^(?!.*d+(?:.d+){2})d*.?d*/?d*.?d*[a-z]*$
See proof. This expression disallows three numbers that have a period between one another thanks to (?!.*d+(?:.d+){2}) negative lookahead.
EXPLANATION
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
(?! look ahead to see if there is not:
--------------------------------------------------------------------------------
.* any character except n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
d+ digits (0-9) (1 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
(?: group, but do not capture (2 times):
--------------------------------------------------------------------------------
. '.'
--------------------------------------------------------------------------------
d+ digits (0-9) (1 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
){2} end of grouping
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
d* digits (0-9) (0 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
.? '.' (optional (matching the most amount
possible))
--------------------------------------------------------------------------------
d* digits (0-9) (0 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
/? '/' (optional (matching the most amount
possible))
--------------------------------------------------------------------------------
d* digits (0-9) (0 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
.? '.' (optional (matching the most amount
possible))
--------------------------------------------------------------------------------
d* digits (0-9) (0 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
[a-z]* any character of: 'a' to 'z' (0 or more
times (matching the most amount possible))
--------------------------------------------------------------------------------
$ before an optional n, and the end of the
string