IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Collection et Stream Java Discussion :

[java.util.regex.Pattern] Regex : contrôler le nombre d'accolades


Sujet :

Collection et Stream Java

  1. #1
    Membre éprouvé

    Inscrit en
    Janvier 2009
    Messages
    467
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 467
    Points : 1 253
    Points
    1 253
    Billets dans le blog
    2
    Par défaut [java.util.regex.Pattern] Regex : contrôler le nombre d'accolades
    Bonjour,

    Je me posais la question suivantes à propos des expressions régulière (regex) :
    Est il possible de contrôler le nombre d'accolade ouverte et fermée { et } pour lors d'un match :

    En fait je cherche à récupérer l'accolade fermante correspondante à une accolade ouvrante que je connais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Ici {
       et au milieu { un certain nombre }
       d accolades {
           { inconue
                 }
           et aussi imbriquées
       }
       avec un nombre inconu à l avance {
           pas facile { ? }
       }
    }
     
    Par contre {
       le schéma continue {
          de la meme {  }
          manière
       }
       en dessous
    }
    L'idée est de pouvoir détecter Ici { jusqu'à l'accolade correspondante : } (ligne 11)


    Nb: cette question n'est pas vraiment purement Java... Mais je n'ai pas trouvé de Forum spécialisé regex...

    .

  2. #2
    Membre éprouvé

    Inscrit en
    Janvier 2009
    Messages
    467
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 467
    Points : 1 253
    Points
    1 253
    Billets dans le blog
    2
    Par défaut
    Ce que j'ai réussi à faire :

    Récupérer toute les structures qui ne contiennent pas d'autres accolades :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Pattern pattern;
    pattern = Pattern.compile("\\{[^\\{\\}]*\\}");
    Donne :
    Après j'ai fait pleins d'essais du genre chercher { ... } .. } ou { .. { .. }

  3. #3
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 621
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 621
    Points : 15 704
    Points
    15 704
    Par défaut
    C'est typiquement le genre de problème pour lesquels tu ne pourras pas t'en sortir avec les expression régulières car elle ne savent pas gérer les structures récursives.
    Le mieux que tu puisse faire avec des regexp est de te limiter a n niveaux de profondeur. Par exemple :
    2 niveaux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    (?s)
    \{
    	(\{.*?\}|.)
    *?\}
    3 niveaux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (?s)
    \{
    	(\{
    		(\{.*?\}|.)
    	*?\}|.)
    *?\}
    4 niveaux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (?s)
    \{
    	(\{
    		(\{
     
    			(\{.*?\}|.)
    		*?\}|.)
    	*?\}|.)
    *?\}
    Ces exemples sont indentés pour être lisible, mais il faut bien sur enlever l'indentation et doubler les '\' si tu les utilises dans une chaine de caractères.


    Si tu veux faire ça proprement, il va te falloir parser le texte toi même ; c'est pas très complexe.
    Il te faut lire la chaine caractère par caractère. Tu incrémentes un compteur quand tu rencontres '{' et décrémentes quand tu rencontres '}'. Quand le compteur reviens a 0 c'est que c'est trouvé.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Oui il n'y a aucune expression régulière qui détecte des expressions de la forme anbn (comme aaabbb), il faut utiliser une pile d'où le compteur comme l'a bien précisé Uther

  5. #5
    Membre éprouvé

    Inscrit en
    Janvier 2009
    Messages
    467
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 467
    Points : 1 253
    Points
    1 253
    Billets dans le blog
    2
    Par défaut
    Ok merci...

    Voici pour ceux que cela intéresse une solution avec un compteur :
    (j'utilise quand même les regex pour ne pas lire le String en entier, mais c'est la même idée)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    /**
     * Look for the next closing curly brackets after a given position
     * Closing curly brackets coming after opening curly brackets are ignored
     * @param s source string
     * @param afterPos the starting position
     * @return the position of the char just after the } or -1 if not found
     */
    public static int findClose(String s, int afterPos) {
    	Pattern pOpen, pClose;
    	Matcher mOpen, mClose;
    	int res, posOpen, posClose, counter;
     
    	res = -1;
    	posClose = afterPos;
    	posOpen = afterPos;
    	counter = 0;
     
    	pOpen = Pattern.compile("\\{");
    	mOpen = pOpen.matcher(s);
    	pClose = Pattern.compile("\\}");
    	mClose = pClose.matcher(s);
     
    	while(counter >= 0 && mClose.find(posClose)) {
    		while(mOpen.find(posOpen) && mOpen.start() < mClose.start()) {
    			posOpen = mOpen.end();
    			counter = counter +1;
    		}
     
    		posClose = mClose.end();
    		counter = counter -1;
    	}
    	if(counter < 0) {
    		res = posClose;
    	}
    	return res;
    }
    Utilisation du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    String s;
    int i;
    //Avec s correspondant au string dans mon premier post
    i = findClose(s, 5); //5 parce que c'est la position apres "Ici {"
    if (i > 0) {
    	System.out.println(s.substring(0, i)); // 0 parce que c'est la position de debut de "Ici {"
    } else {
    	System.out.println("Not found");
    }
    Pour s:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    String s = "";
    s += "Ici {\n";
    s += "   et au milieu { un certain nombre }\n";
    s += "   d accolades {\n";
    s += "      { inconue\n";
    s += "      }\n";
    s += "   et aussi imbriquées\n";
    s += "   }\n";
    s += "   avec un nombre inconu à l avance {\n";
    s += "      pas facile { ? }\n";
    s += "   }\n";
    s += "}\n";
    s += "\n";
    s += "Par contre {\n";
    s += "   le schéma continue {\n";
    s += "   de la meme {  }\n";
    s += "      manière\n";
    s += "   }\n";
    s += "   en dessous\n";
    s += "}\n";

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. java.util.regex.Pattern et ThreadLocal
    Par mickael.camelot dans le forum Langage
    Réponses: 5
    Dernier message: 21/12/2011, 10h28
  2. java.util.regex Class Pattern: expression régulières chiffres romains
    Par bipbipman2003 dans le forum API standards et tierces
    Réponses: 10
    Dernier message: 10/06/2011, 15h24
  3. [Pattern][Regex] vérifier que mon email est valide
    Par anitshka dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 23/05/2011, 13h03
  4. ResourceBundle - java.util.regex.pattern
    Par babalastar dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 14/02/2008, 14h43
  5. [Performance] IndexOf() ou java.util.regex ?
    Par scifire dans le forum Langage
    Réponses: 3
    Dernier message: 27/03/2006, 19h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo