J'ai besoin d'une expression régulière pour sélectionner tout le texte entre deux crochets extérieurs.
Exemple: some text(text here(possible text)text(possible text(more text)))end text
Résultat: (text here(possible text)text(possible text(more text)))
Réponses:
Les expressions régulières ne sont pas le bon outil pour le travail car vous avez affaire à des structures imbriquées, c'est-à-dire à la récursivité.
Mais il existe un algorithme simple pour ce faire, que j'ai décrit dans cette réponse à une question précédente .
la source
Je veux ajouter cette réponse pour référence rapide. N'hésitez pas à mettre à jour.
.NET Regex utilisant des groupes d'équilibrage .
Où
c
est utilisé comme compteur de profondeur.Démo sur Regexstorm.com
PCRE utilisant un modèle récursif .
Démo à regex101 ; Ou sans alternance:
Démo à regex101 ; Ou déroulé pour la performance:
Démo à regex101 ; Le motif est collé sur
(?R)
lequel représente(?0)
.Perl, PHP, Notepad ++, R : perl = TRUE , Python : package Regex avec
(?V1)
pour le comportement Perl.Ruby utilisant des appels de sous-expression .
Avec Ruby 2.0
\g<0>
peut être utilisé pour appeler le modèle complet.Démo chez Rubular ; Ruby 1.9 ne prend en charge que la capture de la récursivité de groupe :
Démo chez Rubular ( groupement atomique depuis Ruby 1.9.3)
API JavaScript :: XRegExp.matchRecursive
JS, Java et autres saveurs regex sans récursivité jusqu'à 2 niveaux d'imbrication:
Démo sur regex101 . Une imbrication plus profonde doit être ajoutée au modèle.
Pour échouer plus rapidement sur des parenthèses déséquilibrées, supprimez le
+
quantificateur.Java : une idée intéressante utilisant les références directes de @jaytea .
Référence - Que signifie cette expression régulière?
la source
(?>[^)(]+|(?R))*+
est donc la même chose que l'écriture(?:[^)(]+|(?R))*+
. Même chose pour le motif suivant. À propos de la version déroulée, vous pouvez mettre un quantificateur possessif ici:[^)(]*+
pour éviter le retour en arrière (au cas où il n'y aurait pas de crochet de fermeture).(...(..)..(..)..(..)..(..)..)
) dans la chaîne du sujet), vous pouvez utiliser un groupe non capturant simple et enfermer le tout dans un groupe atomique:(?>(?:[^)(]+|\g<1>)*)
( cela se comporte exactement comme un quantificateur possessif). Dans Ruby 2.x, le quantificateur possessif est disponible.Vous pouvez utiliser la récursion regex :
la source
Unrecognized grouping construct
.[^\(]*
correspond à tout ce qui n'est pas un crochet ouvrant au début de la chaîne,(\(.*\))
capture la sous-chaîne requise entre crochets et[^\)]*
correspond à tout ce qui n'est pas un crochet fermant à la fin de la chaîne. Notez que cette expression ne tente pas de faire correspondre les crochets; un simple analyseur (voir la réponse de dehmann ) serait plus approprié pour cela.la source
Si vous souhaitez sélectionner du texte entre deux parenthèses correspondantes , vous n'avez pas de chance avec les expressions régulières. C'est impossible (*) .
Cette expression régulière renvoie simplement le texte entre la première ouverture et les dernières parenthèses fermantes de votre chaîne.
(*) À moins que votre moteur d'expression régulière n'ait des fonctionnalités comme l' équilibrage des groupes ou la récursivité . Le nombre de moteurs qui prennent en charge de telles fonctionnalités augmente lentement, mais ils ne sont toujours pas disponibles.
la source
Cette réponse explique la limitation théorique des raisons pour lesquelles les expressions régulières ne sont pas le bon outil pour cette tâche.
Les expressions régulières ne peuvent pas faire cela.
Les expressions régulières sont basées sur un modèle informatique appelé
Finite State Automata (FSA)
. Comme son nom l'indique, unFSA
ne peut se souvenir que de l'état actuel, il n'a aucune information sur les états précédents.Dans le diagramme ci-dessus, S1 et S2 sont deux états où S1 est l'étape initiale et finale. Donc, si nous essayons avec la chaîne
0110
, la transition se déroule comme suit:Dans les étapes ci - dessus, lorsque nous sommes à la deuxième
S2
soit après l' analyse syntaxique01
de0110
la FSA n'a pas d' informations sur le précédent0
en01
car il ne peut se rappeler l'état actuel et le symbole d'entrée suivante.Dans le problème ci-dessus, nous devons connaître le non de la parenthèse ouvrante; cela signifie qu'il doit être stocké à un endroit. Mais puisque
FSAs
cela ne peut pas être fait, une expression régulière ne peut pas être écrite.Cependant, un algorithme peut être écrit pour effectuer cette tâche. Les algorithmes relèvent généralement du domaine
Pushdown Automata (PDA)
.PDA
est un niveau au-dessus deFSA
. PDA dispose d'une pile supplémentaire pour stocker des informations supplémentaires. Les PDA peuvent être utilisés pour résoudre le problème ci-dessus, car nous pouvons `push
` les parenthèses ouvrantes dans la pile et 'pop
' les une fois que nous rencontrons une parenthèse fermante. Si à la fin, la pile est vide, l'ouverture des parenthèses et la fermeture des parenthèses correspondent. Sinon non.la source
Il est en fait possible de le faire en utilisant des expressions régulières .NET, mais ce n'est pas trivial, alors lisez attentivement.
Vous pouvez lire un bel article ici . Vous devrez peut-être également lire les expressions régulières .NET. Vous pouvez commencer à lire ici .
Des équerres
<>
ont été utilisées car elles ne nécessitent pas de fuite.L'expression régulière ressemble à ceci:
la source
C'est le regex définitif:
Exemple:
notez que le
'(pip'
est correctement géré en tant que chaîne. (essayé dans le régulateur: http://sourceforge.net/projects/regulator/ )la source
J'ai écrit une petite bibliothèque JavaScript appelée équilibrée pour aider à cette tâche. Vous pouvez accomplir cela en faisant
Vous pouvez même faire des remplacements:
Voici un exemple JSFiddle plus complexe et interactif .
la source
Pour ajouter à la réponse de Bobble Bubble , il existe d'autres saveurs d'expression régulière où les constructions récursives sont prises en charge.
Lua
Utilisation
%b()
(%b{}
/%b[]
pour les accolades / crochets):for s in string.gmatch("Extract (a(b)c) and ((d)f(g))", "%b()") do print(s) end
(voir démo )Perl6 :
Correspondances entre parenthèses équilibrées multiples sans chevauchement:
Chevauchement de plusieurs correspondances équilibrées entre parenthèses:
Voir la démo .
re
Solution Python non regexVoir la réponse de poke pour savoir comment obtenir une expression entre parenthèses équilibrées .
Solution non regex personnalisable Java
Voici une solution personnalisable permettant des délimiteurs littéraux à un seul caractère en Java:
Exemple d'utilisation:
la source
L'expression régulière utilisant Ruby (version 1.9.3 ou supérieure):
Démo sur rubular
la source
Vous avez besoin des première et dernière parenthèses. Utilisez quelque chose comme ceci:
str.indexOf ('('); - il vous donnera la première occurrence
str.lastIndexOf (')'); - le dernier
Vous avez donc besoin d'une chaîne entre,
la source
la source
La réponse dépend de si vous devez faire correspondre les ensembles de crochets correspondants, ou simplement de la première ouverture à la dernière fermeture dans le texte d'entrée.
Si vous devez faire correspondre les crochets imbriqués correspondants, vous avez besoin de quelque chose de plus que des expressions régulières. - voir @dehmann
Si c'est juste ouvert pour fermer, voir @Zach
Décidez de ce que vous voulez faire avec:
Vous devez décider à quoi votre code doit correspondre dans ce cas.
la source
parce que js regex ne prend pas en charge la correspondance récursive, je ne peux pas faire fonctionner la correspondance de parenthèses équilibrées.
c'est donc un simple javascript pour la version en boucle qui transforme la chaîne "method (arg)" en tableau
le résultat est comme
la source
Alors que tant de réponses mentionnent cela sous une forme quelconque en disant que l'expression régulière ne prend pas en charge la correspondance récursive et ainsi de suite, la principale raison de cela réside dans les racines de la théorie du calcul.
Langue du formulaire
{a^nb^n | n>=0} is not regular
. Regex ne peut correspondre qu'à des éléments qui font partie de l'ensemble régulier de langues.En savoir plus @ ici
la source
Je n'ai pas utilisé l'expression régulière car il est difficile de gérer le code imbriqué. Cet extrait devrait donc vous permettre de récupérer des sections de code avec des crochets équilibrés:
J'ai utilisé cela pour extraire des extraits de code d'un fichier texte.
la source
J'étais également coincé dans cette situation où les modèles imbriqués viennent.
L'expression régulière est la bonne chose pour résoudre le problème ci-dessus. Utiliser le modèle ci-dessous
la source
Celui-ci a également fonctionné
la source
Cela peut être utile à certains:
Analyser les paramètres de la chaîne de fonction (avec des structures imbriquées) en javascript
Faites correspondre les structures comme:
Ici vous pouvez voir l'expression rationnelle générée en action
Cela ne répond pas entièrement à la question OP mais je pense que cela peut être utile à certains venant ici pour rechercher des expressions rationnelles de structure imbriquée.
la source