2009-07-22 4 views
1

Je n'ai pas fait de regex depuis un moment, et je suis un peu rouillé. J'essaye d'analyser les catégories d'une entrée de Wikipedia. Ce dont j'ai besoin, ce sont les cordes individuelles contenues dans un motif qui commence par deux parenthèses ouvertes et se termine par deux parenthèses fermantes.Expression régulière pour les balises imbriquées (contenu Wikimedia)

Cette requête fonctionne la plupart du temps -

(\[\[)(?<category>.*[^\]#])([\]]) 

mais a des problèmes lorsque les crochets de fermeture ont une virgule (« ») à côté d'eux.

Cela a le résultat regrettable que lors de l'analyse du texte suivant -

nlocation = [[Seattle, Washington]], [[United States|USA]]| 

il extrait les éléments suivants pour « catégorie »

Seattle, Washington]], [[United States|USA 

De toute évidence, la virgule est de lancer cette large et il est de trouver l'ensemble suivant. Quel est le meilleur moyen de capturer toutes les valeurs entre les doubles crochets ouverts et fermés?

+0

L'un des rares avantages incontestables de xml est que vous n'avez jamais besoin d'utiliser regex pour les analyser ... –

+2

@ THC4k - Je ne sais pas pour vous, mais mon HTML ne ressemble pas à [[Seattle, Washington]], ça ressemble à Seattle, Washington

Répondre

2

Faites votre caractère générique non gourmand en ajoutant un point d'interrogation:

(\[\[)(?<category>.*?[^\]#])([\]]) 

        ^
        Here is the edit 

Cela va faire correspondre les catégories individuelles.

+0

Je n'ai jamais été fan de la correspondance non-gourmande - je préfère généralement spécifier ce que je ne veux pas dans mon match - mais +1 pour la solution facile. –

+0

Les quantificateurs non-gourmands sont la solution miracle des regex. Quelqu'un pose une question regex, quelqu'un d'autre leur dit d'utiliser des quantificateurs réticents, ça marche, tout le monde est content. Et aucun d'entre eux n'a une idée * pourquoi * cela a fonctionné. –

3

Le problème n'est pas la virgule, le problème est que .* correspondra "]] [[" aussi bien que toute autre chose. * est gourmand - il correspondra autant que possible. Pour le réparer, vous pouvez utiliser la version non-gourmande (comme suggéré par RichieHindle), ou vous pouvez changer .* à [^\]]* - correspondance gloutonne quoi que ce soit sauf fermetures de fermeture. Cela devrait aussi faire l'affaire.

De plus, il ne s'agit pas de balises "imbriquées", mais de [[tag [[inside]] tag]]. Ce n'est probablement pas ce que vous voulez, car je ne pense pas que cela signifie quelque chose dans le balisage de Wikimedia.

0

Je pense que vous rendez cela beaucoup plus compliqué que nécessaire. Est-ce que cela fait ce que vous voulez?

\[\[(?<category>[^\[\]]+)\]\] 
0

La virgule n'est pas pertinente du tout. Vous pourriez avoir confirmé que vous-même avec un test simple.

Et il n'y a pas d'imbrication ici. Wikilinks ne sont pas autorisés à être imbriqués de toute façon.

Vous devez vous assurer que votre motif interne ne peut pas correspondre au double bracket qui ferme un wikilink. De cette façon, chaque fois que rencontre rencontre une séquence à double parenthèse, il arrête d'accumuler plus de caractères dans la correspondance regex. Le problème dans votre expression régulière est que .* correspond tout. Le moyen facile de résoudre ce problème est de use a non-greedy modifier. De cette façon, le match est terminé dès que possible. Si vous ne voulez pas faire cela ou si votre bibliothèque regex ne le supporte pas, vous devez exclure explicitement la séquence qui devrait terminer le pattern.

Une approche naïve serait de simplement exclure crochets de fermeture tout à fait: [^]]*. Ce n'est pas assez bon, cependant. Un unique parenthèse de fermeture est autorisé dans le texte d'un wikilink. Par conséquent, vous devez accepter une seule parenthèse tout en excluant les doubles crochets. Cela devrait le faire:

\[\[  # 2 opening brackets 
(?<category> 
    (
    ]?  # optional bracket 
    [^]] # always a non-bracket 
)* 
) 
]]   # 2 closing brackets 

qui accepte un crochet droit, mais seulement si elle est suivie d'une non-support pour briser la séquence de fermeture. Utilisez l'analyseur html de votre langue respective lorsque vous essayez d'analyser html.

Questions connexes