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