检查字符串是否为整数的正则表达式

3
一个 HTML 表单会返回一个用户输入的数字字符串,如何使用正则表达式判断这个字符串是否是数字。我不想简单地去掉逗号并尝试将其转换为整数,也不喜欢使用 locale.atoi 方法,因为即使字符串是无意义的(例如,locale.atoi('01,0,0') 也可以被转换成数字 100)。

注意,只有当字符串包含逗号时才进行此验证。

正则表达式模式应为:

第1个字符是1-9(不能为零),第2和第3个字符是0-9。接着是3个1-9的数字和重复出现 0 到 2 次的逗号(999,999,999,999 是程序中最大的数字)。最后是3个1-9的数字。

compiled = re.compile("[1-9][0-9]{0,2},(\d\d\d,){0,2}[0-9]{3}")

这不正确地匹配了字符串的末尾,例如:

re.match(compiled, '123,456,78') 

匹配出现了问题。我做错了什么?

你在前面提到了三个数字,但是你的字符串最后只有两个数字。 - Avinash Raj
是的,确切地说就是这样,它不应该匹配,但它却匹配了! - Woody Pride
为什么不将所有表达式分组?([1-9][0-9]{0,2},(\d\d\d,){0,2}[0-9]{3}) 你能发一些匹配的例子吗? - llrs
2个回答

1

更加紧凑

我建议使用更加紧凑的方式:

^[1-9][0-9]{0,2}(?:,[0-9]{3}){0,3}$

请看演示

  • ^断言我们在字符串的开头
  • [1-9]匹配我们的第一个数字
  • [0-9]{0,2}匹配最多两个额外的数字
  • (?:,[0-9]{3})匹配逗号和三个数字,...
  • 最多出现0到3次
  • $断言我们在字符串的结尾

为了验证,您可以执行:

if re.search("^[1-9][0-9]{0,2}(?:,[0-9]{3}){0,3}$", subject):
    # Successful match
else:
    # Match attempt failed

@Downvoter,可以解释一下你对这个紧凑、可工作的模式的评价,并提供一个说明和演示吗? - zx81
非常整洁,':?' 是什么意思? - Woody Pride
我现在明白了,你必须说明你是否在字符串的开头/结尾。在我的例子中,如果我没有这样做,是不是意味着 (\d\d\d,){0,2} 同时匹配 '123,' 和 '456,',而 [0-9]{3} 则匹配 '123' 和 '456'?非常感谢。 - Woody Pride
@WoodyPride,(?:引入了非捕获括号。 - zx81
因为它不是完整的数字,只是“第一个字符是1-9(不是零),第二个和第三个字符是0-9”,但之后还有更多的条件,据我理解也应该匹配。但似乎这对OP有所帮助,也许我错了。 - llrs
显示剩余4条评论

1

如果您想匹配完整的字符串,请确保在正则表达式中指定开头和结尾,例如:

re.compile(r"^[1-9][0-9]{0,2},(\d\d\d,){0,2}[0-9]{3}$")

此外,您会注意到,我使用了原始字符串(r前缀)来避免转义\

编辑

只是为了解释一下您的正则表达式是怎么回事,它匹配的最小子字符串是第一组数字匹配零次,并且第二组也匹配零次的情况:即 "[1-9][0-9]{0},(\d\d\d,){0}[0-9]{3}",这与 [0-9]{3} 相同。由于它可以在字符串的任何位置匹配,因此它可以匹配 "123""456"


我认为我明白了: 在我的例子中,(\d\d\d,){0,2} 同时匹配了 '123,' 和 '456,', 而 [0-9]{3} 则匹配了 '123' 和 '456'。是这样吗?我没意识到你必须指定字符串的开头和结尾。不同之处只在于匹配发生在字符串顺序上 - 是这样的吗? - Woody Pride

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接