2009-02-02 6 views
3

Je travaille sur une simple fonction de remplacement symbolique de notre produit. J'ai presque résolu tout le problème mais j'ai raté une chose. Un jeton doit prendre en charge les attributs, et un attribut peut également être un jeton. Cela fait partie d'un plus grand projet. J'espère que vous pouvez aider. La marque de début est "**#[**" et l'étiquette de fin est "**]**". Dites, # [Prénom], # [Nom], # [Age, WhenZero = "Undisclosed"].Regex: Comment obtenir tout le contenu d'un tag # [QUELQUES TEXTES ICI]

En ce moment j'utilise cette expression "\#\[[^\]]+\]". J'ai ceci fonctionnant mais il a échoué sur cette entrée:

blah blah text here... 
**#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/> 
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"]** 
blah blah text here also... 

Il échoue car il se connecte le premier], il s'arrête là. Il retourne:

*#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/> 
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[Product_FreeShipping]* 

Mon résultat souhaité doit être

*#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/> 
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"]* 
+0

J'ai remplacé: '<' ->' <' – jfs

+0

Il y a encore beaucoup de problèmes avec le balisage. Est-ce que quelqu'un pourrait enlever tous les astérisques? Aucun d'entre eux ne fonctionne comme prévu de toute façon. –

Répondre

1

C'est une petite ligne de frontière pour une expression rationnelle, car elle dépend d'un contexte, mais quand même ...

#\[(\](?=")|[^\]])+\] 

devrait le faire.

L'idée est de mentionner qu'un crochet fermant peut faire partie du contenu analysé s'il est suivi d'un double guillemet, dans le cadre de la fin d'un attribut.

Si cette même tranche carrée étaient partout dans l'attribut, ce serait beaucoup plus difficile ...


L'avantage avec l'expression de préanalyse est que vous pouvez spécifier une expression rationnelle avec une longueur de correspondance non fixée .
Donc, si l'attribut fermeture crochets est pas suivie d'une double citation, mais plutôt par une autre expression connue, vous mettez à jour seulement la partie de préanalyse:

#\[(\](?=</a>")|[^\]])+\] 

correspond uniquement à la deuxième fermeture support carré, depuis la première est suivie par .

Bien sûr, toute sorte d'expression avide (.*]) ne fonctionnerait pas, car il ne correspondrait pas à la deuxième tranche carrée de fermeture, mais la dernière un. (Ce qui signifie qu'il y a plus d'un intermédiaire ], il sera analysé.)

+0

Cela ne fonctionnera pas. Il y a un '' avant '"', pas ']'. – jfs

+0

Merci J.F., je n'ai pas vu les révisions de la question Je viens de mettre à jour ma réponse pour refléter les changements. – VonC

0

Lorsque j'ai fait ce genre de choses avant d'avoir évalué à partir de l'expression la plus interposable avant de passer à des chaînes plus grandes.

Dans ce cas, votre expression régulière devrait probablement essayer de remplacer $ [FreeShipping] par sa valeur avant d'évaluer le plus grand jeton contenant la clause if.

Peut-être que vous pouvez trouver un moyen de remplacer les jetons de valeur est comme $ [site de ce marchand] avant ceux sans $ préfixer le jeton

Ceci est à peu près, mais pas exactement

http://en.wikipedia.org/wiki/Multi-pass_compiler contre http://en.wikipedia.org/wiki/One-pass_compiler

Écrire dans une regex ne sera pas nécessairement plus rapide que de boucler sur quelques regex simples. Tout ce que fait regex est l'analyse de chaînes abstraites.

0

Si vous n'attendez un seul match une entrée donnée, vous pouvez simplement permettre un match gourmand:

/#\[.*\]/ 

Si vous vous attendez à multiples que vous avez un problème parce que vous ne disposez plus du texte normal . Vous aurez besoin d'échapper aux supports internes d'une manière ou d'une autre.

(Regex est un sujet profond - il est tout à fait possible que quelqu'un a une meilleure solution)

0

Je serais intéressé à lear si je me trompe, mais si je me souviens bien, vous ne pouvez pas faire en utilisant des expressions régulières. Cela ressemble à un langage Dyck pour moi et vous auriez besoin d'un automate à pile pour accepter les expressions. Mais je dois admettre que je ne suis pas tout à fait sûr si cela est vrai pour la forme étendue de regexp comme ceux fournis par Perl.

1

Votre Regex correspond exactement à ce que votre condition indique: Commencez avec un crochet carré d'ouverture et associez tout à premier carré de fermeture.

Si vous voulez faire correspondre des crochets imbriqués, vous devez spécifier exactement ce qui est valide lors de l'imbrication. Par exemple, vous pourriez dire que les crochets peuvent être imbriqués lorsqu'ils sont placés entre guillemets.

0

Il est possible d'écrire une regex pour l'exemple que vous avez donné mais en général il échoue. Une seule expression régulière ne peut pas fonctionner pour des expressions imbriquées arbitraires.

Votre exemple montre que votre DSL a déjà des conditions 'if'. Pas avant longtemps Il pourrait évoluer vers un langage Turing-complet.

Pourquoi ne pas utiliser un langage de modèle existant, comme Django template language:

Votre exemple:

blah blah text here... #[IsFreeShipping, 
WhenTrue="<img src='/images/fw_freeshipping.gif'/> 
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"] 
blah blah text here also... 

En utilisant un langage de template Django:

blah blah text here... {% if IsFreeShipping %} 
<img src='/images/fw_freeshipping.gif'/> 
<a href='http://www.hellowebsite.net/freeshipping.aspx'>{{ FreeShipping }}</a> 
{% endif %} blah blah text here also... 
0

Cela fonctionne pour votre échantillon:

#\[(?:[^\]$]+|\$(?!\[)|\$\[[^\[\]]*\])*\] 

Il suppose que les crochets internes ne peuvent pas contenir eux-mêmes des crochets. Si les jetons intérieurs peuvent également contenir des jetons, vous n'avez probablement pas de chance. Certains arômes de regex peuvent gérer des structures récursives, mais les expressions rationnelles qui en résultent sont hideuses même selon les normes regex. : D

Cette regex traite également le '$' comme spécial seulement s'il est suivi d'un crochet carré d'ouverture.Si vous voulez interdire son utilisation, supprimez la deuxième alternative: |\$(?!\[)

Questions connexes