Utilo

Decimal Number Regular Expression – Free, Online, Private

Matches a JSON-style number: optional fraction, optional exponent, no leading zero.

Tester
Sample
Matches (3)
  • 0
  • -12.5
  • 3e-4

The pattern

The pattern follows the shape of a JSON number. 0, -12.5, and 3e-4 match. 00.1 does not, because of the leading zero. 1. does not, because a decimal point must be followed by a digit. .5 does not, because a digit is required before the point. This is the pattern to use when the next step is JSON.parse or a parser with the same rules.

The source is ^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$. The flags on this page are m. i means case-insensitive. m means ^ and $ match at line breaks, which is how the sample can show several candidates. g is not set. The tester finds non-overlapping matches, and without g a pattern with no anchor still reports the matches it walks. The box under the title is a tester with this pattern and the sample already filled in. Edit either one. Nothing you type is uploaded. The same tester, without a preset, is the regex tool.

How to read it

The integer part is the same as the integer pattern: an optional minus, then 0 or a non-zero start. (?:\.\d+)? is an optional fraction. The dot is escaped. \d+ means at least one digit, so a trailing dot fails. (?:[eE][+-]?\d+)? is an optional exponent. The sign inside the exponent is optional and may be plus or minus. Anchors and the m flag make each sample line its own test.

What it will not do

The pattern does not accept a leading plus on the number itself. JSON does not either. It does not accept hexadecimal or a trailing f the way some programming languages do. Magnitude is not checked. 1e999999 matches the shape and may overflow a float. Parse after the match and handle the error. Underscores between digits, as in 1_000, are rejected.

A match is not a parsed value. An email pattern does not send mail, a UUID pattern does not allocate an id, and a password pattern does not store a password. When the next step needs a real parser, use one: the URL constructor, a date library, a semver library, or the converters on this site. The expression is the part you can see.

JavaScript, Python, and Go

The JavaScript snippet uses the RegExp constructor so the source does not have to be escaped for a literal slash. The Python snippet uses a normal string with the same escapes JSON would emit, which keeps \d as a regex digit class. Go's snippet uses a raw string. If the pattern contains a lookahead, the Go snippet says so and does not call MustCompile, because RE2 would reject it at runtime.

JavaScriptconst re = new RegExp("^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$", "m");
const found = text.match(re);
console.log(found ? found[0] : "no match");
Pythonimport re

pattern = re.compile("^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$", re.MULTILINE)
found = pattern.search(text)
print(found.group(0) if found else "no match")
Gopackage main

import (
	"fmt"
	"regexp"
)

func main() {
	text := ""
	re := regexp.MustCompile(`(?m)^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
	fmt.Println(re.FindString(text))
}

Frequently asked questions

Does .5 match?

No. JSON numbers need a digit before the decimal point. Use 0.5.

Does 1. match?

No. A decimal point has to be followed by at least one digit.

Is 3E10 accepted?

Yes. The exponent marker may be e or E, and the sign may be omitted.

Are leading zeros allowed?

Only the single digit 0. 00.1 fails.