Regex pour vérifier si une chaîne de caractères sont incompatibles entre parenthèses?
Dans un script PHP, ce regex dois-je utiliser pour vérifier incompatibles entre parenthèses dans une chaîne de caractères? Les choses que je veux permettre à inclure:
- C'est (ok)
- Ceci (est) (ok)
Choses que je veux éviter:
- C'est )mauvais(
- C'est aussi (mauvaise
- C'est la (mauvaise (trop)
Merci!
Mise à jour: les gars, Vous tous rock. De le faire avec une regex semblait plus délicat qu'il doit avoir, et ces sortes de 2ème niveau des réponses sont ce qui rend stackoverflow belle. Merci pour les liens et le pseudo-code. Je ne sais pas à qui donner la réponse, alors je m'excuse auprès de tous ceux dont les réponses que je ne peux pas accepter.
Avez-vous besoin d'arbitraire parenthèses imbriquées ou vous connaissez pour sûr qu'il n'y a pas plus de un niveau fixe (par exemple, 5 niveaux de profondeur) de nidification possible dans toute la chaîne d'entrée?
Les chaînes sont limitées à environ 300 caractères. Il est certainement possible d'obtenir 300 (s dans une rangée. Ah, la saisie de l'utilisateur 🙂
Les chaînes sont limitées à environ 300 caractères. Il est certainement possible d'obtenir 300 (s dans une rangée. Ah, la saisie de l'utilisateur 🙂
OriginalL'auteur twk | 2009-02-18
Vous devez vous connecter pour publier un commentaire.
Regex n'est pas le bon outil pour le travail. Analyse une chaîne manuellement.
Pseudo-code:
OriginalL'auteur jfs
Vous peut faire cela avec une expression régulière (PCRE, utilisé par PHP, permet récursive modèles. Le Manuel PHP donne un exemple qui est presque exactement ce que vous voulez:
Cela correspond tout correctement parenthesised substring aussi longtemps qu'il commence et se termine avec des parenthèses. Si vous voulez vous assurer que l'ensemble de la chaîne est équilibré, afin de permettre les chaînes comme
"wiggedy(wiggedy)(wiggedy(wack))", voici ce que je suis venu avec:
Voici une explication de la structure, qui peut être plus éclairante que obfuscatory:
Il ya beaucoup de considérations d'efficacité et d'exactitude que de venir avec ces sortes de regexes. Être prudent.
Perl a la même (?R) le sous-groupe. Mais cette fonctionnalité, ainsi que (?? { code }), sont très expérimental, et la documentation indique que leur exacte des effets secondaires sont sujettes à des changements entre les versions. Donc, pour la production de code, n'essayez pas d'utiliser des hacks dans l'automate fini (PCRE).
Chris, avez-vous une référence pour les "très expérimental" avertissement? Le PCRE page de manuel de pcre.org/pcre.txt ne pas dire cela.
C'est vrai pour les regexes en général. Catastrophique retour en arrière peut facilement se produire sans l'aide de la récursivité. La meilleure chose à propos de regexes est leur incroyable puissance et la flexibilité. La pire chose à propos de regexes est leur incroyable puissance et la flexibilité.
+1 - Si maintenant vous avez certainement deux problèmes.
OriginalL'auteur Bennett McElwee
Il n'est pas possible de réaliser cela avec une regex. Accolade de l'appariement nécessite un recursive/fonction de comptage qui n'est pas disponible dans une regex. Vous aurez besoin d'un analyseur syntaxique pour ce.
Plus de détails sont disponibles ici: http://blogs.msdn.com/jaredpar/archive/2008/10/15/regular-expression-limitations.aspx
il s'agit plus d'une sémantique de l'argument, mais au point d'une expression régulière peut faire de la récursivité, ce n'est pas vraiment une regex plus. C'est un contexte exempt de fautes de grammaire. Je me rends compte de ce que signifie vraiment rien à la plupart des gens, bien que la récursivité est rapidement devenu l'un des must have de la fonctionnalité pour les regexes.
Vous avez raison, mais je pense que dans le contexte de l'OP de la question, il est important de souligner que, quelle que soit PHP appelle un "regex", peut effectivement faire ce qu'il demande de faire. (Espérons qu'ils sont encore appelées "regex" pour un certain temps, cfgex ne pas descendre dans la langue en tant que bien. 🙂
En fait je ne savais pas que PHP regex ont récursive capacités (généralement de travailler avec l' .Version Net). cregex est terrible. J'aime modregex mais ce serait confondre perl gars. Peut-être rrregex (récursif prêt regex). Vous devez utiliser un tony le tigre frosted flakes voix à dire que.
OriginalL'auteur JaredPar
D'accord avec le fait que c'est impossible avec une REGEX. Vous pouvez effectuer les opérations suivantes:
OriginalL'auteur nickohrn
Vos exemples ne comprend pas les parenthèses imbriquées... si vous n'êtes pas concerné par l'imbrication, alors cela peut être fait à l'aide de l'expression suivante:
Cela va correspondre à l'encontre de toutes les chaînes dans votre "permettre" de la liste et ne le sont pas contre les chaînes dans votre "empêcher" de la liste. Cependant, elle échoue également à l'encontre de n'importe quelle chaîne avec des parenthèses imbriquées. par exemple, "il (est (pas) ok)"
Comme d'autres l'ont déjà souligné, les expressions régulières ne sont pas le bon outil si vous avez besoin de gérer de nidification.
OriginalL'auteur Ben Blank
D'étendre JaredPar réponse, ce n'est pas très difficile à résoudre sans l'aide d'une regex, il suffit d'écrire une fonction qui examine chaque caractère de la chaîne et incrémente/décrémente un compteur. Si vous trouvez un "(", l'incrémenter, et si vous trouvez un ")", décrémenter. Si le compteur ne va jamais au-dessous de 0, vous pouvez rompre, la chaîne n'est pas valide. Lorsque vous avez traité l'ensemble de la chaîne, si le compteur n'est pas 0, il était d'une incomparable parenthèse ouverte.
OriginalL'auteur Chad Birch
Pourquoi il n'est pas possible avec une regex
Autres réponses sont tout à fait correct, mais je veux juste parler de la théorie de l'informatique... c'est un cas où le savoir de la théorie donne un réel avantage pratique.
Une expression régulière correspond à un automate fini déterministe (DFA), mais parenthèse correspondant nécessitent un contexte de grammaire, qui peut être réalisé comme un automate fini (PDA), mais pas par un DFA.
De ce fait, sans beaucoup de cerveau, nous savons que la réponse est non, et nous n'avons pas à avoir peur qu'il y est quelque chose que nous sommes juste à donnant sur. Ainsi, vous pouvez être confiant dans les réponses ci-dessus, et ne pas s'inquiéter que les auteurs sont tout donnant sur quelque chose quand ils donnent cette réponse.
Presque tous compilateur livres va parler de ce sujet, voici un bref aperçu:
http://books.google.com/books?id=4LMtA2wOsPcC&pg=PA94&lpg=PA94&dq=push-down+finite+automata&source=bl&ots=NisYwNO1r0&sig=ajaSHFXwpPOWG8IfbcfKoqzS5Wk&hl=en&ei=m26cSdf6DZGYsAPB-6SsAg&sa=X&oi=book_result&resnum=6&ct=result
Hmm, quelle fonction? Avez-vous un exemple qui vont travailler sur "((()))", "()()()", "(((", ou "()))"?
Le récursive des sous-masques fonctionnalité. Voir ma réponse à cette question, qui gère correctement les quatre exemples que vous donnez.
Bennett, doux!!
OriginalL'auteur Mark Harrison
Php sans regex:
OriginalL'auteur Jonas Lundman