This seems to work:
^[+]?(?:(?:0*\.0*[1-9][0-9]*)|(?:0*[1-9][0-9]*(?:\.[0-9]*)?))(?:[Ee][-+]?[0-9]+)?$
It tests the entire string using ^
and $
, so it would need modification to work on a substring. Depending on language/environment, \
or other characters may need to be escaped.
Here's a Go program that builds up the regex and tests it:
https://play.golang.com/p/ENHu09Axug4
package main
import (
"fmt"
"regexp"
"strings"
)
// build up regexp string
const (
optLeadingPlus string = "[+]?"
mantissaLessthanOne string = "(?:0*\\.0*[1-9][0-9]*)"
mantissaGreaterorequalOne string = "(?:0*[1-9][0-9]*(?:\\.[0-9]*)?)"
positiveFloatMantissa string = "(?:" +
mantissaLessthanOne +
"|" +
mantissaGreaterorequalOne +
")"
optExponent string = "(?:[Ee][-+]?[0-9]+)?"
regexpPositiveFloat string = "^" + optLeadingPlus + positiveFloatMantissa + optExponent + "$"
)
var (
rePosFloat *regexp.Regexp
)
// require regexp to compile before main
func init() {
rePosFloat = regexp.MustCompile(regexpPositiveFloat)
}
// test a single token and show the result
func test(s string, expected bool) {
r := rePosFloat.MatchString(s)
msg := "passed:"
if r != expected {
msg = "FAILED>"
}
fmt.Printf("%v s=%v, match=%v\n", msg, s, r)
}
func main() {
fmt.Printf("%v\n", regexpPositiveFloat)
tnan := "5.13.7 +0-1 McGillicuddy"
tzero := "0 +0 -0 .0 0. 0.0 00.00 0.000 .000 +00 -00 0000. " +
".0000000000000000000000000000000000000000000000000000000000000000000 " +
"0e50 0e-50 0e0 .0E000 +0e-1"
tneg := "-2 -1 -3.2 -0.001 -.00001 -0.0000001E-99 " +
"-.00000000000000000000000000000000000000000000000000000000000000000000000001 "
tpos := "2 +2 2. +1 1. 1.3 +365.2425 .03 0.3 3.0 6.02e23 0.00001 .01 .00001 " +
".00000000000000000000000000000000000000000000000000000000000000000000000001 " +
"+.01 +.000000000000000000000000000000000000001 1e50 1e+50 1e-50 1E0 +.05E-9"
for _, t := range strings.Split(tnan, " ") {
test(t, false)
}
for _, t := range strings.Split(tzero, " ") {
test(t, false)
}
for _, t := range strings.Split(tneg, " ") {
test(t, false)
}
for _, t := range strings.Split(tpos, " ") {
test(t, true)
}
}
Thanks to tchrist both for that PCRE version and for the excellent test cases.