我尝试在javascript中使用正则表达式,输入元素中不允许使用特殊字符和前导和尾随空格。最大字符长度为50。我使用的正则表达式是
/^[a-zA-Z0-9]+([ ]?[a-zA-Z0-9]+)*$/
但是当字符串很大并且末尾有一个特殊字符时,这会导致问题。在研究中,我发现这是由于灾难性的回溯而发生的,但我无法优化正则表达式。请帮助我找到这个问题的最佳解决方案。我尝试去抖动输入元素的keyup事件,但这也没有解决问题。
kb5ga3dv1#
这就像从空格后面删除可选的量词(?)一样简单:/^[a-zA-Z0-9]+([ ][a-zA-Z0-9]+)*$/应该没问题。我们需要论证两件事:1.* 这不会改变RegEx匹配的内容 :可选的量词是不必要的。Kleene星星(*)已经使整个空格分隔的部分(([ ][a-zA-Z0-9]+))成为可选的。如果没有空格,您将只有字母数字,[a-zA-Z0-9]+将匹配。1. 这将彻底改变运行时 *:一个字符要么是一个空格,要么匹配[a-zA-Z0-9]。RegEx引擎只能进入一种状态:如果是字母数字,则必须留在贪婪量词中;如果它是一个空格,它必须前进,然后期望至少一个字母数字。特别是,什么不能再发生的是,RegEx引擎有 * 两个选项 *:是进入Kleene星星的另一次迭代还是停留在当前的[a-zA-Z0-9]+。我还做了一些修改,将Kleene星星移到前面,并使用i标志来进一步缩短它(然后可以省略A-Z)。空格周围的[和]括号也是不必要的。使用第四只鸟的测试,它是如何执行的:/^([a-z0-9]+ )*[a-z0-9]+$/i .像你当前的RegEx一样,这并不强制执行长度要求。我建议在针对RegEx进行测试之前在JavaScript中强制执行长度要求。这将是最易读和最有效的。
?
/^[a-zA-Z0-9]+([ ][a-zA-Z0-9]+)*$/
*
([ ][a-zA-Z0-9]+)
[a-zA-Z0-9]+
[a-zA-Z0-9]
i
A-Z
[
]
/^([a-z0-9]+ )*[a-z0-9]+$/i
d8tt03nd2#
您可以从匹配单个字符的模式开始,以防止在每一行上触发lookahead,然后Assert0-49个字符。然后将模式添加到lookahead中的捕获组中,然后使用对组1的反向引用来匹配字符串,因为lookahead是原子的。对/i使用不区分大小写的模式
/i
^[a-z0-9](?=[a-z0-9 ]{0,49}$)(?=([a-z0-9]+(?: [a-z0-9]+)*))\1$
参见regex demo。
2条答案
按热度按时间kb5ga3dv1#
这就像从空格后面删除可选的量词(
?
)一样简单:/^[a-zA-Z0-9]+([ ][a-zA-Z0-9]+)*$/
应该没问题。我们需要论证两件事:
1.* 这不会改变RegEx匹配的内容 :可选的量词是不必要的。Kleene星星(
*
)已经使整个空格分隔的部分(([ ][a-zA-Z0-9]+)
)成为可选的。如果没有空格,您将只有字母数字,[a-zA-Z0-9]+
将匹配。1. 这将彻底改变运行时 *:一个字符要么是一个空格,要么匹配
[a-zA-Z0-9]
。RegEx引擎只能进入一种状态:如果是字母数字,则必须留在贪婪量词中;如果它是一个空格,它必须前进,然后期望至少一个字母数字。特别是,什么不能再发生的是,RegEx引擎有 * 两个选项 *:是进入Kleene星星的另一次迭代还是停留在当前的[a-zA-Z0-9]+
。我还做了一些修改,将Kleene星星移到前面,并使用
i
标志来进一步缩短它(然后可以省略A-Z
)。空格周围的[
和]
括号也是不必要的。使用第四只鸟的测试,它是如何执行的:/^([a-z0-9]+ )*[a-z0-9]+$/i
.像你当前的RegEx一样,这并不强制执行长度要求。我建议在针对RegEx进行测试之前在JavaScript中强制执行长度要求。这将是最易读和最有效的。
d8tt03nd2#
您可以从匹配单个字符的模式开始,以防止在每一行上触发lookahead,然后Assert0-49个字符。
然后将模式添加到lookahead中的捕获组中,然后使用对组1的反向引用来匹配字符串,因为lookahead是原子的。
对
/i
使用不区分大小写的模式参见regex demo。