我有一个类似于600/-4.412/11
的字符串和一个看起来像600/11
[optional sign][float or integer]/[optional sign][float or integer]/[optional sign][float or integer]
[optional sign][float or integer]/[optional sign][float or integer]
示例:
1) 600/-4.412/11
2) 600/11
我需要找到一个匹配1的正则表达式和一个匹配2的正则表达式。但是两个表达式都不能选择/匹配另一个。凭借我谦逊的正则表达式知识,我设法建立了这个表达式:
([-+]?[0-9]+(\.?[0-9]+)?\/?){3}
根据http://gskinner.com/RegExr/,这个表达式的问题在于它匹配1)以及2)。希望有人可以解决这个问题或者至少告诉我为什么会发生这种情况,因为我希望我只需要将{3}更改为{2}以获得不同的匹配。
答案 0 :(得分:1)
这是因为表达式中的几乎所有内容都是可选的。 必须出现的唯一内容是单个数字,因此您的表达式也会匹配007
。
因此,解决方案是使表达式的一部分成为必需的。有很多方法可以解决这个问题。一个不完全符合你的描述,但你应该考虑的恕我直言
([-+]?[0-9]+(\.[0-9]+)?(?=/|$))
此表达式将匹配两种类型的输入,但您可以通过查看匹配计数(2或3)来区分它们 - 这相当于在采用分支之前测试两个不同的表达式。
<强>更新强>
上面的表达式过于自由,因为它没有锚定在输入的开头和结尾。这是一个锚定的,因此如果输入包含任何虚假字符,则不匹配:
^([-+]?[0-9]+(\.[0-9]+)?(/(?!$)|$)){2,3}$
打破它:
^ start matching at the beginning
( match the following:
[-+]? optional sign
[0-9]+(\.[0-9]+)? integer or float
( either
/(?!$) a slash that's not trailing
| or
$ end of input
)
){2,3} do this exactly two or three times
$ and make sure there is no other input
答案 1 :(得分:1)
问题在于,您的正则表达式允许重复的子模式,即[-+]?[0-9]+(\.?[0-9]+)?\/?
匹配,而不会将其限制为由/
分隔的数字的每个部分。
对于您的问题中的此示例:600/11
,第一次重复将与600/
匹配,第二次重复将为1
,第三次重复将为最后一次1
。
对于验证,您可以稍微更改它以使其按预期工作:
^([-+]?[0-9]+(\.[0-9]+)?(?:/|$)){3}$
(?:/|$)
强制一个数字(浮点或整数)以/
结束,或者它是字符串的结尾。这将有效地确保每个重复在相同的数字内不匹配。
^
,后面添加了$
,以确保该字符串正好有3个数字。
未删除的文字仍适用于正确的解决方案。
但是,上面的正则表达式是错误。它仍然允许1/2/3/
之类的无效输入匹配(以/
结尾)。我们需要在末尾添加一个额外的断言,以防止上述情况匹配:
^([-+]?[0-9]+(\.[0-9]+)?(?:/|$)){3}(?<!/)$
(?<!/)
是一个零宽度负面后瞻,用于检查字符串结尾前的字符是否为/
。
在这种情况下,以[number]([delimiter][number]){repeat}
形式编写正则表达式的麻烦不大,而不是摆弄([number][delimiter/ending]){repeat}
形式。
以下答案将严格验证输入:
^[-+]?[0-9]+(\.[0-9]+)?(?:/[-+]?[0-9]+(\.[0-9]+)?){2}$
以上是为了匹配正好3个数字的情况。将2
更改为1
(或删除{2}
)以匹配2个数字。