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:
The regex that should match this is:
-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?