Regex 没有灾难性回溯的简单字母数字正则表达式(单间距)

Regex 没有灾难性回溯的简单字母数字正则表达式(单间距),regex,backtracking,Regex,Backtracking,我有下面的正则表达式(可以工作)来允许字母数字(以及'和-)和无双空格: ^([a-zA-Z0-9'-]+\s?)*$ 由于嵌套的分组,这允许灾难性的回溯发生-这是不好的 如何简化此表达式以避免灾难性的回溯?? (理想情况下,第一个和最后一个字符也不允许出现空白)解释 嵌套组不会自动导致灾难性回溯。在您的例子中,这是因为您的正则表达式退化为灾难性回溯的经典示例(a*)* 由于\s在^([a-zA-Z0-9'-]+\s?*$中可选,在输入时没有空格,但字符在允许的列表之外,正则表达式简单地退

我有下面的正则表达式(可以工作)来允许字母数字(以及
'
-
)和无双空格:

  ^([a-zA-Z0-9'-]+\s?)*$
由于嵌套的分组,这允许灾难性的回溯发生-这是不好的

如何简化此表达式以避免灾难性的回溯?? (理想情况下,第一个和最后一个字符也不允许出现空白)

解释 嵌套组不会自动导致灾难性回溯。在您的例子中,这是因为您的正则表达式退化为灾难性回溯的经典示例
(a*)*

由于
\s
^([a-zA-Z0-9'-]+\s?*$
中可选,在输入时没有空格,但字符在允许的列表之外,正则表达式简单地退化为
^([a-zA-Z0-9'-]+)*$

您还可以从原始正则表达式的扩展角度考虑:

[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?...
由于
\s
是可选的,我们可以删除它:

[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+...
我们得到了一系列连续的
[a-zA-Z0-9'-]+
,它们会想方设法在字符之间分配字符,并增加复杂性

解决方案 编写正则表达式以匹配
标记分隔符标记的标准方法。。。分隔符标记
标记(分隔符标记)*
。虽然重写正则表达式可以避免重复
标记
,但我建议不要这样做,因为这样做更难做到正确。为了避免重复,您可能希望通过字符串连接来构造正则表达式

按照上述方法:

^[a-zA-Z0-9'-]+(\s[a-zA-Z0-9'-]+)*$
虽然您可以在这里看到重复,但没有灾难性的回溯,因为正则表达式只能扩展到:

[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+...

\s
[a-zA-Z0-9'-]
是互斥的-只有一种方法可以匹配任何字符串。

谢谢。最后使用^[a-zA-Z0-9'-]+(\s[a-zA-Z0-9'-]+)*$来获得全掷,您可以在边界上允许空白,而不允许双字符
^\s?[a-zA-Z0-9'-]+(\s[a-zA-Z0-9'-]+)*\s?$
真正奇怪的是
\s
可以是CR或LF,但只允许一个。带有
“asdfas\r\nabafbgb”
的文本将不会被缓存。为了避免
\s
和换行问题,您可以使用
\h
水平空白结构,或者
[^\s\r\n]
。或者如果您允许单行中断
(?:[^\S\r\n]|\r?\n)
谢谢您的帮助。所有我真正需要的是允许单一间隔(没有其他像中断等)。您知道一种避免在第一个和最后一个字符处使用空格的方法吗?Struts验证似乎通过了这些空间,尽管regex101.com tester的行为与我所希望的一样。谢谢。它工作得很好!不知道为什么Struts 2似乎允许在开始和结束时使用这个正则表达式