没有前导点的正则表达式和最多一个前导零

5
我该如何编写一个正则表达式来匹配具有以下属性的字符串?:
  1. 包含数字以及只有点作为十进制分隔符(但点不是必需的,这意味着它可以是123123.4123.56)。
  2. 没有前导点(不是.12)。
  3. 只有在后面跟着一个点时才能写前导零(不能像000.12那样,只能是0.12)。
  4. 只有2位小数。

123 是什么情况? - Youcef LAIDANI
@YCF_L 当然,可以。 - Muhammadjon
第三个例子(0.123)违反了规则#4吗? - Andreas
标题说“最多一个零”,但是100.05有3个零,看起来应该是有效的。 - Andreas
@Andreas 是的,你说得对。我现在会进行更改。 - Muhammadjon
@Andreas,我是指最多只有一个前导零 :) - Muhammadjon
3个回答

7

在小数点左侧,您需要一个数字(1个或多个数字),但不以零开头:

[1-9][0-9]*

或者它可以只是零:

0 | [1-9][0-9]*

该值可能具有小数点和小数点后1-2位的数字:

\.[0-9]{1,2}

左侧是必需的。小数点和小数位是可选的:

(?: 0 | [1-9][0-9] * ) (?: \. [0-9]{1,2} )?

第一个非捕获组是必需的,以限制 | 模式的范围。第二个非捕获组是必需的,使组合的“小数点和小数位”模式变为可选。

请注意,这将允许尾随零,例如100.00


根据偏好,[0-9]也可以写成\d。我通常会使用\d,但由于正则表达式还有[1-9],因此我在这里更喜欢[0-9],因为我觉得它有助于澄清区别。

根据正则表达式的使用方式,您可能需要添加 ^ 开头/ $ 结尾锚点。在使用 find()时需要它们,并且在使用 matches()时不需要它们,但不会影响结果:

^(?: 0 | [1-9][0-9] * ) (?: \. [0-9]{1,2} )? $


4
使用负向先行断言确保字符串不以0和另一个数字开头(但可以是只有0,或者0后面跟着点)。

^(?!0\d)\d+(?:\.\d{1,2})?$

解释和示例:https://regex101.com/r/7ymqcn/1

附注:比安德烈斯的答案更有效率(匹配所需步骤更少)


非常感谢您的回答!您分享的链接对于理解和检查正则表达式非常有帮助。 - Muhammadjon

-1

您可以尝试将输入字符串转换为浮点数(这将处理删除前导零和没有零的点,以及如果输入仅为整数,则添加".00",并且您可以设置最大小数位数。如果在转换时抛出异常,则输入不符合要求。然后,您可以将浮点数转换回字符串或将其保留为浮点值进行计算。

请参见: https://docs.oracle.com/javase/7/docs/api/java/lang/Float.html#valueOf(java.lang.String)


OP并不是要求修复输入,而是要验证它。---使用float是一个坏主意,因为它的精度非常低。至少,double会更好一些。BigDecimal会更好,这样就永远不会失去精度。 - Andreas

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