Existe-t-il une expression régulière pour détecter une expression régulière valide?

Est-il possible de détecter une expression régulière valide avec une autre expression régulière? Si oui, veuillez donner un exemple de code ci-dessous.

/ ^ # start of ssortingng ( # 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 ssortingng / 

Ceci est une regex récursive, et n’est pas supporté par de nombreux moteurs regex. Ceux basés sur PCRE devraient le soutenir.

Sans espace et commentaires:

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

.NET ne prend pas en charge directement la récursivité. (Les constructions (?1) et (?R) .) La récursivité devrait être convertie en groupes équilibrés:

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

Compacté:

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

Improbable.

Évaluez-le dans un try..catch ou quelle que soit votre langue.

Non, si vous parlez ssortingctement d’expressions régulières et n’incluez pas certaines implémentations d’expressions régulières qui sont en réalité des grammaires sans contexte.

Il existe une limitation des expressions régulières qui rend impossible l’écriture d’une regex qui correspond à toutes les expressions régulières. Vous ne pouvez pas faire correspondre des implémentations telles que des accolades jumelées. Les expressions rationnelles utilisent beaucoup de telles constructions, prenons [] comme exemple. Chaque fois qu’il y a un [il doit y avoir une correspondance]. Assez simple pour une expression régulière “[. *]”.

Ce qui rend impossible pour les regexes, c’est qu’elles peuvent être nestedes. Comment pouvez-vous écrire une regex qui correspond aux crochets nesteds? La réponse est que vous ne pouvez pas sans une regex infiniment longue. Vous pouvez faire correspondre n’importe quel nombre de parenthèses nestedes par force brute, mais vous ne pouvez jamais correspondre à un ensemble arbitrairement long de parenthèses nestedes.

Cette fonctionnalité est souvent appelée comptage (vous comptez la profondeur de l’imbrication). Une expression régulière par définition n’a pas la capacité de compter.

EDIT: J’ai fini par écrire un article à ce sujet: Limitations des expressions régulières

Bonne question. Les vrais langages réguliers ne peuvent pas décider arbitrairement des parenthèses bien formées et nestedes. Par exemple, si votre alphabet contient ‘(‘ et ‘)’, le but est de décider si une chaîne de caractères a des parenthèses bien formées. Comme il s’agit d’une exigence nécessaire pour les expressions régulières, la réponse est non.

Cependant: si vous desserrez l’exigence et ajoutez la récursivité, vous pourrez probablement le faire. La raison en est que la récursion peut agir comme une «stack» vous permettant de «compter» la profondeur d’imbrication actuelle en poussant sur cette stack.

Russ Cox a écrit un merveilleux traité sur l’implémentation du moteur regex: la correspondance des expressions régulières peut être simple et rapide

Bien qu’il soit parfaitement possible d’utiliser une regex récursive comme MizardX l’a posté, pour ce genre de choses, c’est un parsingur beaucoup plus utile. Les expressions régulières étaient à l’origine destinées à être utilisées avec des langages réguliers, être récursif ou avoir des groupes d’équilibrage n’est qu’un patch.

Le langage qui définit les expressions rationnelles valides est en fait une grammaire sans contexte, et vous devez utiliser un parsingur approprié pour le gérer. Voici un exemple pour un projet universitaire d’parsing syntaxique des expressions rationnelles simples (sans la plupart des constructions). Il utilise JavaCC. Et oui, les commentaires sont en espagnol, bien que les noms de méthodes soient assez explicites.

 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() : { Ssortingng t; IRegularExpression r; } { ( "(" r=Expression() ")" {return r;}) | t=Terminal() { return createTerminal(t); } |  { return createLambda(); } |  { return createEmpty(); } } // Matchea un terminal (digito o minuscula) y devuelve su valor Ssortingng Terminal() : { Token t; } { ( t= | t= ) { return t.image; } } 

Vous pouvez soumettre le regex à preg_match qui renverra false si le regex n’est pas valide. N’oubliez pas d’utiliser le ‘@’ pour supprimer les messages d’erreur:

 @preg_match($regexToTest, ''); 
  • renverra 1 si le regex est ‘//’.
  • renverra 0 si le regex est correct.
  • renverra faux sinon.

Cet exemple sur le wiki pyparsing donne une grammaire pour parsingr certaines expressions rationnelles, dans le but de retourner l’ensemble des chaînes correspondantes. En tant que tel, il rejette ceux qui incluent des termes de répétition illimités, tels que «+» et «*». Mais cela devrait vous donner une idée sur la façon de structurer un parsingur qui traiterait les re.

Essaye celui-là…

 //regular expression for email var pattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if(pattern.test(email)){ return true; } else { return false; }