2011-02-08 2 views
1

J'ai une chaîne contenant n sous-chaînes dans le format suivant que je veux correspondre:Java regex aide

{varName:param1, param2, param2} 

exigences sont les suivantes:

  1. Seul le nomVar (à l'intérieur des accolades) est obligatoire
  2. Aucune limite sur le nombre de paramètres
  3. Aucune restriction sur les espaces à l'intérieur des accolades en dehors des noms var et qui ne doit pas param contenir des espaces

J'aimerais pouvoir capturer varName et chacun des paramètres séparément.

Je suis venu avec une regex qui est presque là, mais pas tout à fait. Toute aide serait appréciée.

+1

Vous dites que vous avez une regex qui est "presque là". Peut-être pourriez-vous poster ce que vous avez géré jusqu'à présent? –

+0

Problème avec ceci est qu'il correspond à la varName (group1) le premier param (group2) et le dernier param (group3) seulement – Tom

+0

\ {([a-zA-Z] +) (?: \ s *: \ s * ([^, \ s] +))? (?: \ s *, \ s * ([^, \ s] +)) * \ s * \} – Tom

Répondre

1
String s = "blah blah\n{varName:param1, param2, param2}\nblah"; 

Pattern p = Pattern.compile(
    "\\{([a-zA-Z]+)(?:\\s*:\\s*([^,\\s]+(?:\\s*,\\s*[^,\\s]+)*))\\}" 
); 
Matcher m = p.matcher(s); 
if (m.find()) 
{ 
    String varName = m.group(1); 
    String[] params = m.start(2) != -1 
        ? m.group(2).split("[,\\s]+") 
        : new String[0]; 

    System.out.printf("var: %s%n", varName); 
    for (String param : params) 
    { 
    System.out.printf("param: %s%n", param); 
    } 
} 

Si vous tenez pour un moyen de faire correspondre la chaîne et de sortir tous les composants avec une regex, ne vous embêtez pas; c'est aussi bon qu'il obtient (sauf si vous passez à Perl 6). En ce qui concerne la performance, je ne m'inquiéterais pas jusqu'à ce que cela devienne un problème.

+0

Oui, merci à tous pour votre aide. Je vois maintenant que j'aboyais le mauvais arbre. – Tom

2

Je me demande s'il serait plus simple d'utiliser judicieusement String.split() plutôt que de se battre avec les expressions rationnelles pour ce qui précède. Les délimiteurs (colons/whitespace/virgules) semblent bien définis.

+0

peut-être, bien que j'ai besoin d'utiliser une regex pour trouver les motifs entiers dans la chaîne environnante, donc pensé que je pourrais aussi bien correspondre les parties internes en même temps – Tom

+0

D'accord, regex ne sont vraiment pas la solution à ce problème. Les oneliners illisibles (et y a-t-il d'autres regex?) Sont horribles à maintenir et la syntaxe est assez simple pour être facilement analysée en quelques lignes. – Voo

1

Que diriez-vous d'une regex, ET un scanner?

import java.util.Scanner; 

public class Regex { 

    public static void main(String[] args) { 
    String string = "{varName: param1, param2, param2}"; 
    Scanner scanner = new Scanner(string); 
    scanner.useDelimiter("[\\s{:,}]+"); 
    System.out.println("varName: " + scanner.next()); 
    while (scanner.hasNext()) { 
     System.out.println("param: " + scanner.next()); 
    } 
    } 
} 
+0

Intéressant que, n'ont pas rencontré la classe Scanner avant. Lire dessus maintenant. – Tom

1

Une solution rapide à psuedocode:

string.match(/{(\w+):([\w\s,]+)}/); 
varName = matches[1]; 
params = matches[2].split(','); 
+0

oui, pensé à cela et ce poste était dernier hourra avant d'abandonner et de le faire. Inquiet un peu sur la performance d'une séparation séparée, car il sera assez haut volume - bien, tbh, n'ont aucune idée à ce sujet. – Tom

0

Ok j'ai une solution dans regex qui semble fonctionner très bien:

\ {\ s * ([^ \ { \}, \ s] +) \ s * (?: (? :: \ s * ([^ \ {\}, \ s] +) \ s *) (?:, \ s * ([^ \ { ? \}, \ s] +) \ s *) *) \}

Ou même garder la prétention de pouvoir comprendre:

name = [^ \ {\}, \ s] +

ws = \ *

de

\ {ws (nom) ws (:? (:: ws (nom) ws) (?: ?, ws (nom) ws) *) \}

Je ne le recommanderais pas mais les tests à court semble indiquer que cela fonctionne - nice casse-tête pour 3 heures du matin)

PS: Si vous comparons la solution de split à ceci ou quelque chose de similaire que je serais intéressé à entendre s'il y avait des différences de performance - je ne pense pas que regex serait particulièrement performant.