有没有正则expression式来检测有效的正则expression式?

是否有可能使用另一个正则expression式检测有效的正则expression式? 如果是这样,请给下面的例子代码。

/ ^ # start of string ( # first group start (?: (?:[^?+*{}()[\]\\|]+ # literals and ^, $ | \\. # escaped characters | \[ (?: \^?\\. | \^[^\\] | [^\\^] ) # character classes (?: [^\]\\]+ | \\. )* \] | \( (?:\?[:=!]|\?<[=!]|\?>)? (?1)?? \) # parenthesis, with recursive content | \(\? (?:R|[+-]?\d+) \) # recursive matching ) (?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers | \| # alternative )* # repeat content ) # end first group $ # end of string / 

这是一个recursion正则expression式,并不被许多正则expression式引擎支持。 基于PCRE的应该支持它。

没有空白和评论:

 /^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/ 

.NET不直接支持recursion。 ( (?1)(?R)构造)。recursion必须转换为计数平衡组:

 ^ # start of string (?: (?: [^?+*{}()[\]\\|]+ # literals and ^, $ | \\. # escaped characters | \[ (?: \^?\\. | \^[^\\] | [^\\^] ) # character classes (?: [^\]\\]+ | \\. )* \] | \( (?:\?[:=!] | \?<[=!] | \?> | \?<[^\W\d]\w*> | \?'[^\W\d]\w*' )? # opening of group (?<N>) # increment counter | \) # closing of group (?<-N>) # decrement counter ) (?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers | \| # alternative )* # repeat content $ # end of string (?(N)(?!)) # fail if counter is non-zero. 

压实:

 ^(?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>|\?<[^\W\d]\w*>|\?'[^\W\d]\w*')?(?<N>)|\)(?<-N>))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*$(?(N)(?!)) 

不太可能。

评估它try..catch或任何您的语言提供。

否,如果您严格讲正则expression式,不包括一些实际上下文无关语法的正则expression式实现。

正则expression式有一个限制,这使得不可能写一个匹配所有正则expression式的正则expression式。 你不能匹配如配对的大括号的实现。 正则expression式使用了许多这样的构造,让我们以[]为例。 每当有一个[必须有一个匹配]。 足够简单的正则expression式“[。*]”。

什么使正则expression式不可能是它们可以嵌套。 你怎么能写一个匹配嵌套括号的正则expression式? 答案是你不能没有一个无限长的正则expression式。 你可以通过蛮力匹配任意数量的嵌套parens,但是你永远不能匹配任意长的嵌套括号。

这个function通常被称为计数(你正在计算嵌套的深度)。 根据定义,正则expression式不具备计数能力。

编辑:完成写关于这个博客文章: 正则expression式的限制

好问题。 真正的正规语言不能决定任意深度嵌套的良好forms的括号。 也就是说,如果您的字母表中包含“(”和“)”,那么目标是确定这些string是否具有良好匹配的括号。 由于这是正则expression式的必要条件,所以答案是否定的。

但是:如果你放松了这个需求并添加了recursion,你可以这样做。 原因是recursion可以作为一个“栈”,让你通过推入堆栈来“计数”当前的嵌套深度。

Russ Cox写了关于正则expression式引擎实现的精彩论文: 正则expression式匹配可以简单而快速

虽然MizardX已经发布了使用recursion正则expression式是完全可能的,但对于这种事情来说,parsing器更有用。 正则expression式原本打算用于正规语言,recursion或平衡组只是一个补丁。

定义有效正则expression式的语言实际上是一种上下文无关语法,您应该使用适当的parsing器来处理它。 下面是一个parsing简单正则expression式的大学项目的例子(没有大部分构造)。 它使用JavaCC。 是的,评论是用西class牙语,但方法名称是不言而喻的。

 SKIP : { " " | "\r" | "\t" | "\n" } TOKEN : { < DIGITO: ["0" - "9"] > | < MAYUSCULA: ["A" - "Z"] > | < MINUSCULA: ["a" - "z"] > | < LAMBDA: "LAMBDA" > | < VACIO: "VACIO" > } IRegularExpression Expression() : { IRegularExpression r; } { r=Alternation() { return r; } } // Matchea disyunciones: ER | ER IRegularExpression Alternation() : { IRegularExpression r1 = null, r2 = null; } { r1=Concatenation() ( "|" r2=Alternation() )? { if (r2 == null) { return r1; } else { return createAlternation(r1,r2); } } } // Matchea concatenaciones: ER.ER IRegularExpression Concatenation() : { IRegularExpression r1 = null, r2 = null; } { r1=Repetition() ( "." r2=Repetition() { r1 = createConcatenation(r1,r2); } )* { return r1; } } // Matchea repeticiones: ER* IRegularExpression Repetition() : { IRegularExpression r; } { r=Atom() ( "*" { r = createRepetition(r); } )* { return r; } } // Matchea regex atomicas: (ER), Terminal, Vacio, Lambda IRegularExpression Atom() : { String t; IRegularExpression r; } { ( "(" r=Expression() ")" {return r;}) | t=Terminal() { return createTerminal(t); } | <LAMBDA> { return createLambda(); } | <VACIO> { return createEmpty(); } } // Matchea un terminal (digito o minuscula) y devuelve su valor String Terminal() : { Token t; } { ( t=<DIGITO> | t=<MINUSCULA> ) { return t.image; } } 

您可以提交正则expression式preg_match,如果正则expression式无效,将返回false。 不要忘记使用“@”来抑制错误信息:

 @preg_match($regexToTest, ''); 
  • 将返回1,如果正则expression式是“//”。
  • 将返回0,如果正则expression式没问题。
  • 否则返回false。

pyparsing wiki上的这个例子给出了parsing一些正则expression式的语法,目的是返回一组匹配的string。 因此,它拒绝那些包含无限重复条款的重复条款,如“+”和“*”。 但它应该给你一个关于如何构build一个parsing器来处理重新的想法。