【问题标题】:Do browsers support different HTML5 pattern regexp features?浏览器是否支持不同的 HTML5 模式正则表达式功能?
【发布时间】:2014-04-17 02:26:46
【问题描述】:

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

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

添加它是为了帮助在客户未能输入有效号码时快速通知他们,然后再进行服务器端验证。

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

我读了specs,它只是说:

如果指定,该属性的值必须与 JavaScript 模式生成相匹配。 [ECMA262]

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

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

【问题讨论】:

  • 因为您的问题是“我在哪里可以了解更多关于不同浏览器中模式支持之间的怪癖?”我投票决定将此作为离题关闭,因为它要求找到工具或参考。如果您可以更新您的问题以询问特定的怪癖,我认为这将是主题。
  • Javascript 有自己的正则表达式引擎,不使用 PCRE 库。
  • @Casimir:为您更新了措辞。 ;)
  • @zzzzBov:我在这里联系的原因是我完全无法通过谷歌挖掘任何东西。而且,看到 SO 在现代互联网信息领域中作为编程信息摘要/存档的作用越来越大,我认为提出这个问题是合适的。
  • @Eirik,虽然问“一个具体的、可回答的问题”是合适的,但要求非现场参考是题外话,因为它鼓励仅链接的答案可能难以选择一个是“正确的”,并且容易受到链接腐烂的影响。

标签: javascript regex html pcre


【解决方案1】:

这个问题似乎是一个仅限于 IE 的错误。您的规范链接已经失效,这里缺少 IE:

...除了模式属性与整个值匹配,而不仅仅是任何子集(有点好像它暗示了一个 ^(?: 在模式的开头和一个 )$ 在结尾)

您实际上可以通过对自己的模式执行此操作来修复此错误 - 即:

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

这在 IE9 和 IE10 以及 Chrome 中都适用于我。见updated fiddle

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

如果您阅读了 EMCA 5.1 规范,则在第 15.10.2.3 节中,它谈到了如何评估替代方案。基本上,| 的每个“部分”都会从左到右进行评估,直到找到匹配的部分。除非“续集”出现问题,否则会假定该值,在这种情况下,将评估交替中的其他可能性。

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

一旦正则表达式引擎(没有强制整个字符串匹配的锚点)返回 true,即存在匹配,微软的一些工程师采取了捷径并告诉 pattern 属性也检查匹配的部分是否等于整个字符串,这就是失败的来源。引擎只匹配字符串的一部分,即使它可能匹配更多,所以二次检查失败,认为最后有多余的输入。

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

这与 EMCA 规范有关的原因是,如果引擎被告知要匹配整个字符串,它会在遇到小数点并尝试匹配替换的第二部分时回溯,找到并匹配 (\.[0-9{2}) ,并且整个事情都会奏效。


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

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

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

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

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

【讨论】:

  • 哇。 1:由于某种原因,我在编写 JS RE 时总是忘记使用字符类。 2:由于没有人回答这个问题,我仍然找不到任何关于类似问题的信息,我同意这一定是一个IE错误。我接受你的回复,因为我疯了似乎合乎逻辑,所有浏览器应该都有工作相同的正则表达式引擎。感谢您了解如何创建 Microsoft 错误并与他们一起提出问题。 3:你最后的图案很漂亮。很好地抓住* 导致有趣的比赛。
猜你喜欢
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 2014-08-31
相关资源
最近更新 更多