JSON numbers Regular Expression

Building on Andrew Cheong's fine answer, here's a version that is Bash-compatible. The subtle differences take a while to get just right.

-?(0|[1-9][[:digit:]]*)(\.[[:digit:]]+)?([eE][+-]?[[:digit:]]+)?

In the end, the differences are just that \d is replaced by [[:digit:]] and the ?: are dropped from the alternation clauses.

Here's a script you can paste into a Bash shell to verify its performance. The regex is surrounded by ^ and $ to match the start and end of line respectively, to check for stray trailing or leading characters.

while read line; do
    if [[ $line =~ ^-?(0|[1-9][[:digit:]]*)(\.[[:digit:]]+)?([eE][+-]?[[:digit:]]+)?$ ]]
    then
        echo "$line is a number"
    else 
        echo "$line NOT a number"
    fi
done << END
1
-1
a
1a
a1
-1.0
1.
.0
.
-.0
+
+0
+.0
22
55.75466
-44.565
55e-2
69234.2423432 E78
69234.2423432E78
-
0123
END

In Bash 4.4.12, I get:

1 is a number
-1 is a number
a NOT a number
1a NOT a number
a1 NOT a number
-1.0 is a number
1. NOT a number
.0 NOT a number
. NOT a number
-.0 NOT a number
+ NOT a number
+0 NOT a number
+.0 NOT a number
22 is a number
55.75466 is a number
-44.565 is a number
55e-2 is a number
69234.2423432 E78 NOT a number
69234.2423432E78 is a number
- NOT a number
0123 NOT a number

For reference, here's the "number" diagram from http://www.json.org/fatfree.html:

JSON number

The regex that should match this is:

-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?

Tags:

Regex

Json