【问题标题】:.NET Regex Not working as it should.NET 正则表达式无法正常工作
【发布时间】:2010-01-25 19:48:13
【问题描述】:

我有以下正则表达式模式:(.NET 1.1 正则表达式验证器)

^(?=.*[A-Za-z])[a-zA-Z0-9@\\-_\\+\\.]{6,32}$

我需要满足以下要求:

6 到 32 个字符 必须至少包含一个字母。 允许的字符是 字母(a-z, A-Z), 号码(0-9), @(“at”符号), .(句号), _(下划线), +(加号), -(减号)。

任何以数值开头的条目似乎都被“跳过”,直到遇到非数值。

123abc 失败
123abcde 失败
123abcdef 通过

所以我看到它在数值之后“计算”前瞻,为什么?

谢谢。

【问题讨论】:

  • 您的正则表达式在我看来很好,它在 .NET 3.5 中使用 Regex.Match 进行测试。

标签: .net regex validation


【解决方案1】:

这很可能是 .NET 1.1 中的一个错误。您的所有“失败”示例都使用 Regex Hero,它基于使用 .NET 2.0 Regex 实现的 Silverlight。

您可以尝试使用积极的look-behind 断言,看看是否能解决问题:

^[a-zA-Z0-9@\-_\+\.]{6,32}(?<=.*[A-Za-z])$

编辑:考虑到这是一个 ASP.NET 验证器,您应该仔细检查它是否没有通过客户端验证 (javascript)。某些浏览器不支持某些高级功能(例如零宽度前瞻/后视)。

尝试通过在RegularExpressionValidator 上将EnableClientScript 设置为false 来禁用客户端验证,看看是否能解决问题。如果是这样,那么这是一个浏览器支持问题,我建议您将验证分为两部分:

  1. ^[a-zA-Z0-9@\-_\+\.]{6,32}$ # must be 6-32 characters
  2. ^.*[A-Za-z].*$ # must contain a letter

【讨论】:

  • .NET 是否支持可变宽度的lookbehinds?
  • 我不相信,虽然我不熟悉这个概念。
  • 是的,.NET 正则表达式支持未知宽度的lookbehinds。至少,它们在 .NET 3.5 中是这样的;他们是否在 .NET 1.1 中做过,以及它是否正常工作,我不能说。
  • 我明白你现在的意思了(它们在 .NET 中被称为零宽度后视),是的,它们受支持。
  • 其实,“零宽度”只是指它们不消耗任何字符;前瞻、后瞻、字边界 (\b) 和锚点 (^$\A\Z\z) 都是零宽度断言。 “未知宽度”是我不明智的尝试缩写“能够匹配可变数量的字符,没有限制”。 Java 和 PHP (PCRE) 后视并不像大多数其他风格一样仅限于固定宽度的匹配,但它们也不像 .NET 的后视那样完全不受限制。
【解决方案2】:

您是否尝试过重构正则表达式?例如:

^(?=[a-zA-Z0-9_@+.-]{6,32}$).*[A-Za-z].*$

或者只是“填充”你的前瞻,所以它必须一直匹配到最后:

^(?=.*[A-Za-z].*$)[a-zA-Z0-9_@+.-]{6,32}$

也许这会重置匹配位置,以便第二部分可以从头开始匹配。当然,这不应该是必要的,但我看不出为什么 你的 正则表达式不能像所写的那样工作。

【讨论】:

    【解决方案3】:

    它在数字之后计算前瞻,因为您允许与

    (?=.*[A-Za-z])
    

    .* 表示“在零个或多个字符之后”。

    如果你想强制以字母开头,请修改你的模式:

    ^[A-Za-z][-a-zA-Z0-9@_+.]{5,31}$
    

    【讨论】:

    • (?= ) 是一个零宽度正向前瞻断言,因此“光标”在检查后被重置。
    • 他不想在开头断言一个字母,只是字符串包含一个字母。
    • 没有问题!我的答案中的正则表达式如何公平?
    • 那么我们在某处遗漏了一块拼图。您提供的示例字符串都与您的问题中的模式相匹配。例如,您的程序的实际输入是否包含超过 6 到 32 个字符的字段?
    • 但它们不匹配。在 IE 的 .NET 1.1 中尝试一下。