可能是重复问题:
是否有一个正则表达式来检测有效的正则表达式?
查找正则表达式的正则表达式?
我有一个应用程序,允许用户输入正则表达式。如何检查任何正则表达式输入并确保它们是有效的,因为如果它们无效,则会出现preg_match错误?
我不想在preg_match之前使用“@”,所以如果有一种方法可以检查用户输入的正则表达式的有效性,那就太好了。
PHP的正则表达式系统似乎对我来说过于复杂,难以为其编写正则表达式。
可能是重复问题:
是否有一个正则表达式来检测有效的正则表达式?
查找正则表达式的正则表达式?
我有一个应用程序,允许用户输入正则表达式。如何检查任何正则表达式输入并确保它们是有效的,因为如果它们无效,则会出现preg_match错误?
我不想在preg_match之前使用“@”,所以如果有一种方法可以检查用户输入的正则表达式的有效性,那就太好了。
PHP的正则表达式系统似乎对我来说过于复杂,难以为其编写正则表达式。
在数学上,使用正则表达式无法验证一个正则表达式。这是因为(正式的)正则表达式只能识别 正则语言。语言是任何一组字符串。例如,所有十进制数的集合是一种语言(顺便说一下,可以使用正则表达式描述),所有有效正则表达式的集合也是一种语言。正则 语言是仅需要 固定有限内存(不随输入大小变化的函数)才能识别的语言。
包含所有有效正则表达式的语言不是正则语言,因此使用正则表达式无法识别一个正则表达式。
要理解这一点,请注意正则表达式中包含必须匹配的括号。因此,如果出现了“(”,那么后面必须出现“)”。这是不可能用具有固定有限内存的机器来描述的。因为,如果有一种方法可以做到这一点,并且您的正则表达式具有K个不同状态的有限内存(对于某个整数K),则由K个开括号后跟K个闭括号组成的表达式,虽然是一个有效的正则表达式,但无法被该机器识别——这是一个矛盾(请注意,在形式语言中,我们的假设是文本处理每次处理一个字符,从左到右,这与应用正则表达式相同)。我们把描述正则表达式的这种语言称为上下文无关语言而不是正则语言。
(使用泵引理可以轻松证明正则表达式不构成正则语言)
因此,在识别正则表达式时存在一个基本的计算机科学问题:数学上不可能使用正则表达式进行识别。
有限状态自动机可以识别正则语言,即具有有限状态但没有内存的机器。要解决您的问题,您需要添加一些与输入大小相关的内存。由于正则表达式是上下文无关的(幸运的是它们不是某种晦涩难懂的语言),因此可以使用下推自动机在线性时间内识别。这是一个“for”循环,一次一个标记(通常是字符),并在堆栈上跟踪看到的内容,即以先进后出的方式“推入”数据,稍后再“弹出”数据。 (将数据推送到堆栈的示例:“我需要记住稍后找到匹配的`)`!”;您可以按需多次“推”它;当您需要检查是否实际上需要已匹配前面的开括号时,稍后可以“弹出”它)。
当然,编写自己的正则表达式识别引擎可能会有点负担-但是如果您想这样做,应该知道上述限制。更明智的做法是使用已经存在的机制来处理它--我怀疑您可以将该工作交给正则表达式库或更善于处理正则表达式的语言,如Perl;但是@-方法听起来也不算太糟糕的想法:它可能很慢,但是您的用户可能会输入非常慢的正则表达式;而且这可能是一种不好的做法,但在您的情况下,似乎是可用的最佳解决方法。
有关更多信息,请参见维基百科中的以下文章:
希望这有所帮助!
preg_match()
如果发生错误会返回FALSE
。
preg_match
。您可以使用Ajax进行实时验证,或者在提交表单后进行验证。
您也可以尝试通过将表达式传递给JavaScript正则表达式引擎来进行验证,但是JavaScript的正则表达式语法不完全兼容PHP的语法。
preg_match(…) === false
。 - Gumbo让用户提交正则表达式几乎肯定是个坏主意。
有些表达式非常昂贵。请尝试以下内容:
preg_match('/(.*){1,32000}[bc]/','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
仅仅30个字符的输入就能导致这样的结果!它们看起来并不都像这样:/^(?:(\d+)|::)*$/
在PCRE中也是指数级的时间复杂度。
首先想到的方法是在调用preg_match($sanatized_user_regex, "");
后使用preg_last_error()
。如果返回的不是PREG_NO_ERROR
,则响应相应的错误消息。