浏览器是否支持不同的HTML5模式正则表达式功能?

时间:2014-03-12 18:09:40

标签: javascript regex html5 pcre

我在网站上面向客户的付款表单中有一个简单的RegEx模式:

<input type="text" pattern="(|\$)[0-9]*(|\.[0-9]{2})"
       title="Please enter a valid number in the amount field" required>

在进入服务器端验证之前,已添加它以帮助在客户输入有效号码时快速通知客户。

在四个客户打电话抱怨说他们无法提交表格因为他们的浏览器不断告诉他们他们输入的金额不正确,我做了一些挖掘并发现IE10 +不喜欢那个表达式的背面 - 输入的 not 包含小数点的任何金额都被接受,带有小数的任何内容都被拒绝。该模式适用于我的开发环境(Chrome 30+)和Opera 12,但Firefox 27根本无法验证它。

我读了specs,其中只说:

  

如果指定,则属性的值必须与JavaScript Pattern生成匹配。 [ECMA262]

由于支持pattern的唯一浏览器是capable of supporting ECMAScript 5,因此我认为这包括对所有Javascript正则表达式的完全支持。

在哪里可以了解有关不同浏览器中pattern支持之间的怪癖的更多信息?

1 个答案:

答案 0 :(得分:2)

这个问题似乎只是一个IE浏览器的错误。您对规范的链接已经过时了,继续IE的缺失:

  

...除了pattern属性与整个值匹配,而不仅仅是任何子集(有点像暗示a ^(?:在模式的开头和a)$ at the end)

你可以通过你自己的模式来实际修复这个错误 - 即:

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

在IE9和IE10以及Chrome中,这对我有用。见updated fiddle

发生这种情况的技术原因有点复杂:

如果您在15.10.2.3节中阅读了EMCA 5.1规范,那么它将讨论如何评估备选方案。基本上,每个部分都是&#39; |从左到右进行评估,直到找到匹配的\$[digits][empty]。除非“续集”中存在问题,否则将假定该值,在这种情况下,将评估交替中的其他可能性。

IE正在做的是使用替换的空白部分匹配字符串的开头,并且它有效:$12.12匹配pattern的开头直到小数点。 IE的正则表达式引擎(正确地)说这是一个匹配,因为子字符串匹配,并且它没有被告知要检查字符串的末尾。

一旦正则表达式引擎(没有强制整个字符串匹配的锚点)返回true,表示匹配,Microsoft的一些工程师拿了一个快捷方式并告诉(\.[0-9{2})属性也检查匹配part等于整个字符串,以及失败的来源。引擎只匹配字符串的一部分,即使它可能匹配更多,所以二次检查失败,认为最后有无关的输入。

这个案子很微妙,所以我并不感到惊讶它之前没有被抓住过。我创建了一个错误报告https://connect.microsoft.com/IE/feedback/details/836117/regex-bug-in-pattern-validator,以查看是否有来自Microsoft的回复。

这与EMCA规范有关的原因是,如果发动机被告知要匹配整个字符串,那么当它达到小数点并且试图匹配交替的第二部分时,它会回溯,找到并匹配{{1

。整个事情都会奏效。


现在,对于一些解决方法:

  • 将锚点^(?:)$添加到您的模式中

  • 不要使用空的替换。就个人而言,我喜欢使用可选的$来代替这些情况。您的模式变为(\$?)[0-9]*(\.[0-9]{2})?并且会起作用吗?是一个贪婪的匹配,如果可能,引擎将消耗整个字符串,而不是交替,这是第一次匹配

  • 在您的更改中交换订单。如果首先测试较长的字符串,它将首先匹配,并首先使用。这已经出现在其他语言中 - Why order matters in this RegEx with alternation?

PS:请注意*的数字。现在,&#34; $&#34;是有效匹配,因为*允许0位数。我对你的完整正则表达式的建议是(\$)?(\d+)(\.\d{2})?