在正则表达式中限制字符长度

9

我正在使用以下正则表达式,没有限制任何字符长度:

var test =  /^(a-z|A-Z|0-9)*[^$%^&*;:,<>?()\""\']*$/ // Works fine

在上述示例中,当我尝试将字符长度限制为15时,它会抛出一个错误。
var test =  /^(a-z|A-Z|0-9)*[^$%^&*;:,<>?()\""\']*${1,15}/    //**Uncaught SyntaxError: Invalid regular expression**

如何将上述正则表达式修改为只匹配长度不超过15个字符的情况?

为什么这个标签既有C#又有JavaScript? - Peter Mortensen
1
关于.NET,请参考我在类似问题上的这个答案 - InSync
1个回答

21
你不能对锚点应用量词。相反,为了限制输入字符串的长度,请在开头使用一个以前瞻锚定的方式。
// ECMAScript (JavaScript, C++)
^(?=.{1,15}$)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*$
^^^^^^^^^^^

// Or, in flavors other than ECMAScript and Python
\A(?=.{1,15}\z)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*\z
^^^^^^^^^^^^^^^

// Or, in Python
\A(?=.{1,15}\Z)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*\Z
^^^^^^^^^^^^^^^

另外,我猜你想要用 (a-z|A-Z|0-9)* 匹配零个或多个字母或数字。应该写成 [a-zA-Z0-9]*(即在这里使用字符类)。 为什么不在末尾使用限定量词,比如 {1,15}

量词仅适用于左侧的子模式,无论是组、字符类还是文字符号。因此,^[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']{1,15}$ 将有效地限制第二个字符类 [^$%^&*;:,<>?()\"'] 的长度为 1 到 15 个字符。而 ^(?:[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*){1,15}$ 将把长度不受限制的两个子模式的序列(因为 *(以及 +)可以匹配无限数量的字符)限制在 1 到 15 次,但我们仍未限制整个输入字符串的长度。

前瞻限制如何工作?

(?=.{1,15}$) / (?=.{1,15}\z) / (?=.{1,15}\Z) 这个正向前瞻出现在^/\A(注意,在Ruby中,\A是唯一只匹配整个字符串开头的锚点)即字符串开头的位置。它是一个零宽断言,在检查其子模式是否与后续字符匹配后,仅返回true或false。因此,这个前瞻尝试匹配任意1到15个字符(由于限定量词{1,15}),但不能匹配字符串末尾的换行符(由于$/\z/\Z锚点)。如果我们从前瞻中移除$ / \z / \Z锚点,前瞻将只要求字符串包含1到15个字符,而总字符串长度可以是任意的。
如果输入字符串可能包含换行序列,您应该使用[\s\S]可移植任意字符正则表达式构造(它适用于JS和其他常见的正则表达式风格):
// ECMAScript (JavaScript, C++)
^(?=[\s\S]{1,15}$)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*$
 ^^^^^^^^^^^^^^^^^

// Or, in flavors other than ECMAScript and Python
\A(?=[\s\S]{1,15}\z)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*\z
  ^^^^^^^^^^^^^^^^^^

// Or, in Python
\A(?=[\s\S]{1,15}\Z)[a-zA-Z0-9]*[^$%^&*;:,<>?()\"']*\Z
  ^^^^^^^^^^^^^^^^^^

不太确定你是否需要这个正则表达式。它会匹配0个或多个字母或数字,然后匹配0个或多个不在$%^&*;:,<>?()"'字符集合中的字符。请澄清哪些字符串是有效的(你想要匹配的)以及哪些是无效的。 - Wiktor Stribiżew
如果您的字符串中有换行符,请使用 (?=[\s\S]{1,15}$) 替换第一个前瞻。 - Wiktor Stribiżew
在C#中,当尝试将regEx分配给一个字符串时,上面的代码将不起作用。我需要这样做吗 ^(?=.{1,15}$)[a-zA-Z0-9][^$%^&;:,<>?()""']*$ - Viku
如果您使用普通字符串字面量,它将正常工作。使用逐字字符串字面量,它看起来像 var rx = new Regex(@"^(?=.{1,15}$)[a-zA-Z0-9]*[^$%^&*;:,<>?()""']*$") - Wiktor Stribiżew
@WiktorStribiżew,我读了这篇关于仅使用前瞻进行验证的文章(不仅限于字符串长度),如此:\A(?=[^a-z]*[a-z])(?=(?:[^A-Z]*[A-Z]){3})(?=\D*\d)\w{6,10}\z - 你对这种方法有什么看法? - Max Koretskyi
1
@Maximus 对比原则是您模式中适当的方法。虽然它不涉及限制输入字符串长度,但它是一个特定的验证问题。顺便说一下,这个正则表达式在JS中无法使用。 - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接