2010-08-23 8 views
4

J'ai un problème simple, mais je suis incapable de résoudre ce problème. Soit ma chaîne a un format ID: dddd, avec l'expression régulière suivante:aux prises avec des expressions régulières conditionnelles

/^ID: ([a-z0-9]*)$/ 

ou comme suit: ID: 1234 Status: 232, donc avec l'expression régulière suivante:

/^ID: ([a-z0-9]*) Status: ([a-z0-9]*)$/ 

Maintenant, je veux faire une expression régulière qui peut gérer les deux. La première chose que je suis venu avec était le suivant:

/^ID: ([a-z0-9]*)$|^ID: ([a-z0-9]*) Status: ([a-z0-9]*)$/ 

Il correspond, mais je cherchais dans les expressions régulières conditionnelles, et pensait que quelque chose devrait être possible le long des lignes de (pseudo-codish)

if the string contains /Status:/ 
    /^ID: ([a-z0-9]*)$/ 
else 
    /^ID: ([a-z0-9]*) Status: ([a-z0-9]*)$/ 

seulement, je ne peux pas l'exprimer correctement. Je pensais que je devrais utiliser /?=/ mais je n'ai aucune idée de comment. Quelque chose comme

/((?=Status)^ID: ([a-z0-9]*) Status: ([a-z0-9]*)$|^ID: ([a-z0-9]*)$/ 

mais cela ne fonctionne pas.

Pouvez-vous m'aider?

+0

Votre dernier exemple n'est pas une expression régulière valide. Il a une parenthèse ouverte trop. –

+1

L'ID contient-il toujours quatre caractères alphanumériques? Si oui, pourquoi écrivez '*' au lieu de '{4}'? Pourrait-il y avoir des majuscules et des minuscules? –

+0

C'était juste un exemple. Le nombre de chiffres n'est pas connu à l'avance. – nathanvda

Répondre

6

Vous cherchez ^ID: (\d+)(?: Status: (\d+))?$

modifier: Puisque la question est marqué Ruby il convient de mentionner que, selon les deux this question et this flavour-comparison, Ruby ne fait pas de regex conditionnelle.

http://www.regular-expressions.info est une excellente source sur le sujet.

+0

@jerhinesmith: le titre mentionne re conditionnel, mais le problème à résoudre peut être résolu sans eux. J'utilise (?: ) pour que le motif ne corresponde pas. De cette façon, $ 1 et $ 2 contiendra les nombres correspondants dont le dernier est optionnel. –

+1

Je suis d'accord, et cela a parfaitement du sens, mais si Ruby ne supporte pas la vraie 'regex conditionnelle', cela devrait au moins être souligné dans la réponse. Je pense davantage aux futurs visiteurs de cette question (de google, etc.) et à première vue, il semblerait que pendant que vous résolvez le problème, il n'y a aucune mention quant à * pourquoi * ils devraient utiliser cette méthode et * pas * utiliser regex conditionnel. – jerhinesmith

+0

@jerhinesmith: Vous avez raison. Edité en conséquence. –

3

Vous avez besoin d'un .* dans votre préanalyse: (Rubular)

/(?=.*Status)^ID: ([a-z0-9]*) Status: ([a-z0-9]*)$|^ID: ([a-z0-9]*)$/ 

Cependant, pour votre exemple spécifique que vous n'avez pas besoin d'un test avant. Vous pouvez simplement utiliser la ? quantificateurs à la place: (Rubular)

/^ID: ([a-z0-9]*)(?: Status: ([a-z0-9]*))?$/ 
+0

Merci pour le lien vers la documentation, et les deux exemples. – nathanvda

2

Fait intéressant, selon this question, Ruby 1.8/1.9 ne prend pas en charge les expressions régulières conditionnelles.

Avez-vous (ou l'un des répondeurs) lu autrement? Si c'est le cas, il peut être utile de mettre à jour la question liée afin qu'elle ne fournisse plus d'informations incorrectes.

+0

Assertions/Lookarounds Regex et regex conditions sont deux choses différentes. – polygenelubricants

+0

N'est-ce pas la question sur les conditions générales regex? Je suppose que je ne suis pas sûr de voir ce que vous voulez dire. Cette question et la question liée semblent toutes deux utiliser le format général '(? (Prédicat) yes-pattern | no-pattern)', donc à moins que je manque quelque chose, elles sont très liées. – jerhinesmith

+0

Ha! Cela expliquerait les choses :) – nathanvda