2010-04-19 26 views
0

J'ai passé beaucoup de temps à trouver une simple regex pour retourner un groupe (seulement 1er groupe).regex retourner groupe conditionnel

Donc la chaîne peut être - "Aucun achat requis" ou "Achat de 50,00 $ d'épicerie est nécessaire." J'essaye d'écrire une regex qui peut analyser "Non" ou "50" basé sur la chaîne donnée.

C'est ce que j'ai écrit.

(?:(No) monthly maintenance|Purchase of \$([\d\.]+ worth groceries) 

Cela fonctionne bien, mais je veux que ma sortie soit en tant que 1er groupe/groupe 1 seulement.

+0

Avec quelle langue travaillez-vous par curiosité? Il pourrait y avoir une meilleure façon de gérer cela après l'analyse. – gnarf

Répondre

1

Pourquoi ne pas simplement utiliser /(?:No monthly maintenance|Purchase of $([0-9.]+) worth groceries)/. La correspondance échouera si elle ne se trouve pas dans l'un de ces formats, et le groupe 1 correspond à '' pour le cas "Aucune maintenance mensuelle" ou le numéro pour les autres cas.

Si vous avez vraiment besoin de capturer la chaîne No ou le nombre, vous pourriez avoir besoin pour obtenir un peu plus compliqué et faire quelque chose comme:

/(?:Purchase of $)?([0-9.]+|No) (?:monthly maintenance|worth groceries)/ 
1

La plupart des langues comptent les groupes correspondants afin, que ils sont dans un groupe non-capturant ((?:...|...)), donc forcer la partie intéressante dans le premier groupe de capture pourrait être plus de problèmes que cela en vaut la peine. En fonction de la langue que vous utilisez, vous pouvez essayer d'utiliser deux expressions régulières précompilées différentes et renvoyer le groupe correspondant de la première correspondance, de telle sorte que vous puissiez facilement insérer la partie intéressante dans le premier groupe.

0

Je ne suis pas sûr que vous pouvez obtenir le résultat dans le numéro de groupe 1, mais vous pouvez obtenir les résultats apparaissent dans le même groupe nommé. Voici un exemple dans PowerShell:

$input1 = 'Purchase of $50.00 worth groceries is required' 
$input2 = 'No monthly maintenance required' 

$re = '(?:(?<xyz>No) monthly maintenance|Purchase of \$(?<xyz>[\d\.]+) worth groceries)' 

$match = [regex]::Match($input1, $re) 
$match.Groups['xyz'] 

$match = [regex]::Match($input2, $re) 
$match.Groups['xyz'] 

Ce qui donne le résultat suivant:

Success : True 
Captures : {50.00} 
Index : 13 
Length : 5 
Value : 50.00 

Success : True 
Captures : {No} 
Index : 0 
Length : 2 
Value : No 

toutes les langues ne prennent en charge les groupes nommés cependant. Comme PowerShell s'exécute sur .NET Framework, cela fonctionne pour n'importe quel langage .NET.

+0

Les groupes nommés sont assez communs ces jours-ci, mais très peu de saveurs permettent d'utiliser le même nom deux fois dans une regex, comme vous l'avez fait. Ce qui est dommage, car c'est une fonctionnalité très pratique. –