可能重复:
Is there a regular expression to detect a valid regular expression?
Regular expression for finding a regular expression?
我有一个应用程序,允许用户输入正则表达式。如何检查正则表达式的任何输入并确保它们是有效的,因为如果它们不存在则会出现preg_match错误?
我不想在preg_match之前使用'@',所以如果有办法检查正则表达式的用户输入的有效性那么好。
PHP的正则表达式系统对我来说似乎太复杂了,无法为它们提供正则表达式。
答案 0 :(得分:29)
在数学上,使用正则表达式验证正则表达式是不可能的。这是因为(正式)正则表达式只能识别常规语言。语言是字符串的任何 set 。例如,所有十进制数的集合是一种语言(可以使用正则表达式来描述);所有有效正则表达式的集合也是一种语言。 常规语言是只需要识别固定有限内存(不是输入大小的函数)的语言。
包含所有有效正则表达式的语言不是常规语言;因此,使用正则表达式识别正则表达式是不可能的。
要理解这一点,请注意正则表达式中包含必须匹配的括号。因此,如果“(”已经发生,则“)”必须在以后发生。使用仅具有固定有限内存的机器无法描述这一点。因为,如果是的一种方法,并且你的正则表达式具有 K 不同状态的有限记忆(对于某些整数K),带有K个括号的表达式然后K关闭括号,虽然有效的正则表达式无法被该机器识别 - 矛盾(请注意,在正式语言中,我们的假设是文本处理一次发生一个字符,从左到右,对于应用的正则表达式,它是相同的)。我们将语言称为描述正则表达式的语言无上下文而不是常规。
(使用 Pumping Lemma 证明正则表达式不能形成常规语言是微不足道的)
因此,使用正则表达式识别正则表达式存在一个基本的计算机科学问题:在数学上不可能这样做。
有限状态自动机可以识别常规语言,即具有有限状态但没有内存的机器。要解决您的问题,您需要添加一些取决于输入大小的内存。正则表达式,因为它们是无上下文的(幸运的是它们不是一些模糊的,难以识别的语言类型)可以使用下推式自动机在线性时间内识别。这是一个“for”循环,它一次通过表达式一个标记(通常是一个字符),并跟踪它在堆栈上看到的内容,即它“推送”它所篡改的数据“弹出“以先到先得的方式。 (推送到堆栈的数据示例:“我需要记得在以后找到匹配的`)”!你可以根据需要多次“推”这个;你可以稍后“弹出”它,当你需要检查你是否真的需要以前匹配一个左括号时。)
当然,为正则表达式编写自己的识别引擎会有点开销 - 但如果你想这样做,你应该知道上述限制。使用已有的机制来做这件事更明智 - 我怀疑你可以把这份工作交给正则表达式库或者更热衷于处理正则表达式的语言,比如Perl;但是@ -method听起来并不是一个想法太糟糕了:它可能很慢,但你的用户可能会输入非常慢的正则表达式;这可能是一种不好的做法,但在你的情况下,这似乎是最好的解决方案。
维基百科的一些相关文章:
我希望这有帮助!
答案 1 :(得分:10)
preg_match()
会返回FALSE
。
preg_match
空字符串您可以使用Ajax来验证实时,也可以在表单提交后进行验证 你也可以尝试通过将表达式提供给javascript regexp引擎进行验证,但是js regexp语法与php的语法不是100%兼容。
答案 2 :(得分:6)
让用户提交正则表达式几乎肯定是一个坏主意。
有些表达非常昂贵。试试这个:
preg_match('/(.*){1,32000}[bc]/','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
这只是输入的30个字符!它们看起来都不是这样:/^(?:(\d+)|::)*$/
在PCRE中也是指数时间。
答案 3 :(得分:2)
首先想到的是在调用preg_match($sanatized_user_regex, "");
后使用preg_last_error()
如果您获得PREG_NO_ERROR
以外的任何内容,则会回复相应的错误消息。
答案 4 :(得分:2)
你的问题有点含糊不清。您是否希望验证正则表达式的“语法”,或确保正则表达式实际解析出应用于字符串的内容。我认为在任何一种情况下,你都应该将验证留给用户(例如,提供一个调试/文本框,他们可以输入一个字符串来匹配它们的正则表达式。如果正则表达式有问题或者找不到匹配项,请显示“未找到”错误。)
在验证正则表达式本身方面,您可能希望从一个简单的验证器开始,该验证器检查只有有效字符(例如正则表达式语法的一部分,如$,^ \ t等)是其正则表达式的一部分,但我认为试图验证正则表达式中的逻辑结构可能相当复杂。也许有一些库可以验证正则表达式语法,但我不知道任何。