正则匹配一个数字(python实现)

问题描述

给定一组字符串,判断该字符串是否为一个合法的数字,要求如下

  1. 基本整数数字是 0-9 的组合
  2. 整数不可有前导 0 (如: 012 就不合法)
  3. 小数包含(x.y, .y, x.)三种形式,此时 x 和 y 符合第 1 条且可以有前导 0
  4. 无论整数或小数都可以选择在最前方加入+-之一或者不加,以表达该数字的正负
  5. 数字支持”x^y”的形式以表达 x 的 y 次方的意义,^不能作为一个数字的开头或结尾,同时 x 和 y 均为符合前 4 条条件的数字
  6. 数字支持”xey”的形式以表达 x 乘以 10 的 y 次方的意义,e 不能作为一个数字的开头或结尾,同时 x 符合前 4 条条件,y 符合条件 1 和 4(即:允许前导 0 的整数)

测试样例

  • “+1.23” is True
  • “-1.23” is True
  • “1.23” is True
  • “.23” is True
  • “1.” is True
  • “0.” is True
  • “+123” is True
  • “-123” is True
  • “123” is True
    -
  • “1.23e+123” is True
  • “1.23e-123” is True
  • “1.23e123” is True
  • “1.23e0123” is True
    -
  • “1.23^+123” is True
  • “1.23^-123” is True
  • “1.23^123” is True
    -
  • “1.23^+1.23” is True
  • “1.23^-1.23” is True
  • “1.23^1.23” is True
  • “1.23^.23” is True
  • “1.^1.” is True
  • “1.^0.” is True
    -
  • “” is False
  • “a.” is False
  • “.” is False
    -
  • “-1.2.3” is False
  • “-1.-2” is False
  • “0123” is False
    -
  • “1.23e1.2” is False
  • “1.23e” is False
  • “1.23e1e2” is False
  • “1.23e1^2” is False
    -
  • “1.23^1.2.3” is False
  • “1.23^” is False
  • “1.23^0123” is False
  • “1.23^1^2” is False
  • “1.23^1e2” is False

思路

最开始的思路是先确定数字中是否包含 e 或者^符号,如果有,用其将数字切开,分别对前后进行判断,后来整理清楚要求后,发现可以用正则来进行匹配,正则的整体方案也基本等价于一开始的思路

  1. 对于小数使用\d*.\d+ 来匹配 x.y .y 的形式, \d+. 来匹配 x.的形式
  2. 对于整数使用[1-9]\d*来匹配无前导 0 的形式,\d+ 来匹配有前导 0 的形式
  3. 对以上的几种形式再与- + e ^ 等符号进行按要求的连接即可形成完整的正则

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import re


def numberCheck(numberStr):
numberRegex = re.compile("[-+]?("
"(\d*\.\d+)|" # match x.y .y format
"(\d+\.)|" # match x. format
"([1-9]\d*)" # match Integer format(without lead zero)
")" # a simple number (both Integer and Double)
"("
"(e[+-]?\d+)" # if "e" in number, we need a Integer(can lead with zero) below
"|"
"(\^[+-]?((\d*\.\d+)|(\d+\.)|([1-9]\d*)))" # if "^" in number, we need a simple number below
")?"
)
return numberRegex.fullmatch(numberStr) is not None


def testNumberCheck():
assert numberCheck("+1.23") is True
assert numberCheck("-1.23") is True
assert numberCheck("1.23") is True
assert numberCheck(".23") is True
assert numberCheck("1.") is True
assert numberCheck("0.") is True

assert numberCheck("+123") is True
assert numberCheck("-123") is True
assert numberCheck("123") is True

assert numberCheck("1.23e+123") is True
assert numberCheck("1.23e-123") is True
assert numberCheck("1.23e123") is True
assert numberCheck("1.23e0123") is True

assert numberCheck("1.23^+123") is True
assert numberCheck("1.23^-123") is True
assert numberCheck("1.23^123") is True

assert numberCheck("1.23^+1.23") is True
assert numberCheck("1.23^-1.23") is True
assert numberCheck("1.23^1.23") is True
assert numberCheck("1.23^.23") is True
assert numberCheck("1.^1.") is True
assert numberCheck("1.^0.") is True

assert numberCheck("") is False
assert numberCheck("a.") is False
assert numberCheck(".") is False

assert numberCheck("-1.2.3") is False
assert numberCheck("-1.-2") is False
assert numberCheck("0123") is False

assert numberCheck("1.23e1.2") is False
assert numberCheck("1.23e") is False
assert numberCheck("1.23e1e2") is False
assert numberCheck("1.23e1^2") is False

assert numberCheck("1.23^1.2.3") is False
assert numberCheck("1.23^") is False
assert numberCheck("1.23^0123") is False
assert numberCheck("1.23^1^2") is False
assert numberCheck("1.23^1e2") is False


if __name__ == '__main__':
testNumberCheck()
一瓶肥仔快乐水