2010-05-25 4 views
0

je chaîne dans le format suivant:Matching (et remplacement) des groupes de texte dans une chaîne

bla IIF ((doc.PostTypeId == 1), (Parse (doc.Id)> 1000), (doc.ParentId> 1000)) bla

et je veux le convertir en:

bla (doc.PostTypeId == 1 Parse (doc.Id?)> 1000: doc.ParentId> 1000 blah

Jusqu'ici j'utilise le chaîne suivante regex pour le match

IIF\((?<one>[^,]*?),\ (?<two>[^,]*?),\ (?<three>[^,]*)\)

Mais je vais avoir des problèmes d'équilibre tous les supports, est-il une meilleure façon ou est RegEx le mauvais outil pour cela?

+0

Quelle langue? –

+0

Avez-vous absolument besoin de vous débarrasser des parenthèses intérieures?Sinon, il semblerait que votre regex serait plus simple. – John

+0

@John, non les parenthèses intérieures peuvent rester si c'est plus facile. @Bears, je le fais en C#, mais je pensais que regex était assez général? –

Répondre

1

En général, les expressions régulières ne peuvent pas gérer correctement les parenthèses d'équilibrage, car cela nécessite de compter la profondeur de l'imbrication, qui peut être arbitrairement profonde, et les expressions régulières ne peuvent stocker qu'un nombre fini d'états. . Cela dit, je vais supposer que les changements que vous faites n'ont pas de parenthèses imbriquées plus profondément que, disons, trois ou quatre de profondeur - auquel cas cela devient possible. Voici comment le construire jusqu'à:

Il est facile de faire correspondre une séquence sans parenthèses à tous:

EXPR0: [^()]* 

Nous pouvons l'utiliser pour créer une expression régulière qui correspond à une seule expression non-imbriquée entre parenthèses:

PAREN1: \(EXPR0\) 

Que se passe-t-il à côté d'une expression contenant jusqu'à un niveau de parenthèses? Eh bien, c'est juste un mélange de PAREN1s avec des caractères non-parenthèses:

EXPR1: (?:PAREN1|EXPR0)* 

étant donné que, nous pouvons bien sûr correspondre à une expression équilibrée entre parenthèses jusqu'à un niveau d'imbrication:

PAREN2: \(EXPR1\) 

qui nous pouvons étendre pour correspondre à une expression équilibrée avec pas plus de deux niveaux de() de la même manière

EXPR2: (?:PAREN2|EXPR0)* 

et ainsi de suite:

PAREN3: \(EXPR2\) 
EXPR3:  (?:PAREN3|EXPR0) 
PAREN4: \(EXPR3\) 
... 

Vous pouvez alors l'utiliser pour construire le match de remplacement que vous voulez faire - quelque chose le long des lignes de:

IIF\(?<one>EXPR5),(?<two>EXPR5),(?<three>EXPR5)\) 

(en fait, vous aurez besoin de modifier les choses pour que les expressions expr5 don ne correspond pas aux virgules non-uniformisées, mais il devrait être assez clair comment faire cela j'espère :)

Bien sûr, cela vaut la peine d'écrire un programme court jetable pour générer le re requis plutôt que de le construire manuellement!

+0

J'apprécie la réponse en profondeur, je voudrais pouvoir vous donner plus que +1 pour l'effort que vous avez mis !! –

Questions connexes