"contains 10-14 digits" 的正则表达式正前瞻无法正常工作
Regex positive lookahead for "contains 10-14 digits" not working right
我有一个正则表达式,用于验证 phone 数字字符串是空的,还是包含任何格式的 10-14 位数字。它适用于至少需要 10 个数字但继续匹配超过 14 个数字。我以前很少使用前瞻,也没有看到问题。这是评论中的预期解释:
/// ^ - Beginning of string
/// (?= - Look ahead from current position
/// (?:\D*\d){10,14} - Match 0 or more non-digits followed by a digit, 10-14 times
/// \D*$ - Ending with 0 or more non-digits
/// .* - Allow any string
/// $ - End of string
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
这在 asp.net MVC 5 站点中使用 System.ComponentModel.DataAnnotations.RegularExpressionAttribute
,因此它在服务器端使用 .NET 正则表达式,在 javascript 客户端使用 jquery 验证。如果字符串包含超过 14 位数字,如何让它停止匹配?
正则表达式的问题
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
是\D
和|
之间没有行尾锚点。例如,考虑字符串
12345678901234567890
其中包含 20 位数字。前瞻将得到满足,因为 (?:\D*\d){10,14}
将匹配
12345678901234
然后 \D*
将匹配零个非数字。相比之下,正则表达式
^(?=(?:\D*\d){10,14}\D*$|\s*$).*$
会失败(因为它应该)。
但是,不需要向前看。可以将前面的表达式简化为
^(?:(?:\D*\d){10,14}\D*)?$
将外部非捕获组设为可选允许正则表达式根据需要匹配空字符串。
最后一个正则表达式可能有问题,如 link 所示。考虑字符串
\nabc12\nab12c3456d789efg
(?:\D*\d)
的第一个匹配项是 \nabc1
(因为 \D
匹配换行符),第二个匹配项是 2
,第三个匹配项是 \nab1
,以此类推,共匹配11
个,满足10-14个数字的要求。这无疑不是故意的。解决方案是将正则表达式更改为
^(?:(?:[^\d\n]*\d){10,14}[^\d\n]*)?$
[^\d\n]
匹配数字和换行符以外的任何字符。
我有一个正则表达式,用于验证 phone 数字字符串是空的,还是包含任何格式的 10-14 位数字。它适用于至少需要 10 个数字但继续匹配超过 14 个数字。我以前很少使用前瞻,也没有看到问题。这是评论中的预期解释:
/// ^ - Beginning of string
/// (?= - Look ahead from current position
/// (?:\D*\d){10,14} - Match 0 or more non-digits followed by a digit, 10-14 times
/// \D*$ - Ending with 0 or more non-digits
/// .* - Allow any string
/// $ - End of string
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
这在 asp.net MVC 5 站点中使用 System.ComponentModel.DataAnnotations.RegularExpressionAttribute
,因此它在服务器端使用 .NET 正则表达式,在 javascript 客户端使用 jquery 验证。如果字符串包含超过 14 位数字,如何让它停止匹配?
正则表达式的问题
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
是\D
和|
之间没有行尾锚点。例如,考虑字符串
12345678901234567890
其中包含 20 位数字。前瞻将得到满足,因为 (?:\D*\d){10,14}
将匹配
12345678901234
然后 \D*
将匹配零个非数字。相比之下,正则表达式
^(?=(?:\D*\d){10,14}\D*$|\s*$).*$
会失败(因为它应该)。
但是,不需要向前看。可以将前面的表达式简化为
^(?:(?:\D*\d){10,14}\D*)?$
将外部非捕获组设为可选允许正则表达式根据需要匹配空字符串。
最后一个正则表达式可能有问题,如 link 所示。考虑字符串
\nabc12\nab12c3456d789efg
(?:\D*\d)
的第一个匹配项是 \nabc1
(因为 \D
匹配换行符),第二个匹配项是 2
,第三个匹配项是 \nab1
,以此类推,共匹配11
个,满足10-14个数字的要求。这无疑不是故意的。解决方案是将正则表达式更改为
^(?:(?:[^\d\n]*\d){10,14}[^\d\n]*)?$
[^\d\n]
匹配数字和换行符以外的任何字符。