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

Python Discussion :

Recherche d'une regex toute simple (mais pas pour moi)


Sujet :

Python

  1. #1
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 751
    Points
    1 751
    Par défaut Recherche d'une regex toute simple (mais pas pour moi)
    Bonjour,
    quelqu'un pourrait-il me donner un moyen via un regex de tester qu'une chaîne est de l'une des cinq formes suivantes ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    {---
    (...){---
    [...]{---
    (...)[...]{---
    [...](...){---
    Les trois tirets indiquent que ce qui suit l'accolade peut-être n'importe quoi.

    Les trois points de supsension ne peuvent contenir que des nombres, que des lettres non accentuées (majuscules et minuscules), ainsi que les signes '=' , '_' , ';' et '|' (sans les guillemets simples).

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 483
    Points : 9 282
    Points
    9 282
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    C'est codé de façon très rustique, mais ça a l'air de fonctionner:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    motif = r"^({)|(\([0-9a-zA-Z=_;|]+\){)|(\([0-9a-zA-Z=_;|]+\)\[[0-9a-zA-Z=_;|]+\]{)|(\[[0-9a-zA-Z=_;|]+\]{)|(\[[0-9a-zA-Z=_;|]+\]\([0-9a-zA-Z=_;|]+\){)"
     
    L = ("{nyosnvygteonvyudsom",
         "(12azER){nyosnvygteonvyudsom",
         "(12azER=_;|)[12azER=_;|]{nyosnvygteonvyudsom",
         "[12azER=_;|]{nyosnvygteonvyudsom")
     
    for x in L:
        print re.match(motif,x)!=None
    Ce qui renvoie "True" 4 fois.

    Pour comprendre comment c'est codé, il suffit de décomposer (c'est comme ça que je les construis):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    motif = r"
    ^
    ({)
    |
    (\([0-9a-zA-Z=_;|]+\){)
    |
    (\([0-9a-zA-Z=_;|]+\)\[[0-9a-zA-Z=_;|]+\]{)
    |
    (\[[0-9a-zA-Z=_;|]+\]{)
    |
    (\[[0-9a-zA-Z=_;|]+\]\([0-9a-zA-Z=_;|]+\){)
    "
    Il y a moyen de faire plus concis, parce qu'il y a des motifs qui se répètent, mais je n'ai plus le temps ce soir.

    Attends tout de même d'autres propositions.

    Tyrtamos

  3. #3
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 751
    Points
    1 751
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Il y a moyen de faire plus concis, parce qu'il y a des motifs qui se répètent, mais je n'ai plus le temps ce soir.

    Attends tout de même d'autres propositions.
    Ok.

    Merci pour ta proposition qui semble bien fonctionner.

    PS : Pour le motif, j'ai fait comme ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    motif =  = re.compile(r'''
        ^                                               # debut de la chaine
        ({)                                             # cas du type {---
        |                                               # ou
        (\([0-9a-zA-Z=_;|]+\){)                         # cas du type (...){---
        |                                               # ou
        (\([0-9a-zA-Z=_;|]+\)\[[0-9a-zA-Z=_;|]+\]{)     # cas du type (...)[...]{---
        |                                               # ou
        (\[[0-9a-zA-Z=_;|]+\]{)                         # cas du type [...]{---
        |                                               # ou
        (\[[0-9a-zA-Z=_;|]+\]\([0-9a-zA-Z=_;|]+\){)     # cas du type (...)[...]{---
        $                                               # fin de la chaine
        ''' ,re.VERBOSE)

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 483
    Points : 9 282
    Points
    9 282
    Billets dans le blog
    6
    Par défaut
    A mon avis, le dernier '$' est inutile. De plus, il est affecté au dernier sous-motif, et impose que son '{' soit le dernier caractère de la ligne. De ce fait, le dernier sous-motif ne détecte plus '[xx](xx){xxx'. Si tu veux absolument mettre un '$', il faut entourer les 5 sous-motifs par un couple de parenthèses, et mettre '.+' devant '$' et après la parenthèse fermante ('.'=n'importe quel caractère et '+'=un ou plus).

    Mais ça marche aussi bien sans ce '$'.

    Tyrtamos

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    Tu dois pouvoir faire ca en une unique ligne en faisant un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    motif = re.compile(r"(\(.*?\))?(\[.*?\])?{")
    En décomposition ca donne:
    • cherche 0 ou 1 occurrence de (...)
    • puis cherche 0 ou 1 occurrence de [...]
    • puis cherche {...


    Je pense que c'est à ca que pensais Tyrtamos. J'ai essayé sur son exemple, ca retourne 4 fois True aussi.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    Outch, ca ne passe pas ton dernier motif, cette expression. Parce que [] et () peuvent s'inverser et que je ne le prends pas en compte.

    Je n'ai plus trop le temps de trouver mieux, la. Mais t'as l'idée générale, en tout cas.

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Points : 923
    Points
    923
    Par défaut
    Avec un peu de réflexion, il y a moyen de regrouper un peu, dans le genre de ce qu'a proposé shadowsam
    Ce que tu cherches en fait c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    (...) (optionnel)
    [...] (optionnel)
    {---
    OU
    [...](...){---
    C'est-à-dire, en regex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    (?:
      (?:\(\[a-zA-Z0-9=_;|]+\))?
      (?:\[\[a-zA-Z0-9=_;|]+\])?
    ) | (?:
      \[\[a-zA-Z0-9=_;|]+\]
      \(\[a-zA-Z0-9=_;|]+\)
    ) {
    Pas besoin du ^ si on fait un match.

    Mais à mon avis, dans ton cas, le plus efficace (si tu as besoin de performances) serait de vérifier caractère par caractère.
    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
    expr = re.compile('[a-zA-Z0-9=_;|]')
     
    def valide(chaine):
        bloc = False
        etat = [None, None] # None: Pas trouvé, False: Ouvert, True: Ouvert et fermé.
        corres = {'(': 0, ')': 0, '[': 1, ']': 1}
        for c in chaine:
            if bloc:
                if expr.match(c) is None: #Caractère non autorisé
                    return False
                if c in ')]':
                    if etat[corres[c]] is False: #Bonne correspondance
                        etat[corres[c]] = True
                        bloc = False
                    else: #Mauvaise correspondance
                        return False
            else:
                if c in '([':
                    if etat[corres[c]] is None: #Pas encore trouvé
                        etat[corres[c]] = False
                        bloc = True
                    else: #Déjà trouvé
                        return False
                elif c == '{': #Fin du test, vérification de la fermeture
                    return (False not in etat)
                else:
                    return False
        return False

  8. #8
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 751
    Points
    1 751
    Par défaut
    oiffrig, ton code fonctionne avec les changements suivants.
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    import re
     
    pattern_declaParam = re.compile('[a-zA-Z0-9=_;|]')
     
    def testMeth(chaine):
    # D'après :
    # http://www.developpez.net/forums/d724077/autres-langages/python-zope/general-python/recherche-regex-toute-simple-moi/
     
    # On doit avoir quelque chose du type avec = éventuellement à la place de {.
    #    {...
    # ou
    #    (...){...
    # ou
    #    [...]{...
    # ou
    #    (...)[...]{...
    # ou
    #    [...](...){...
        bloc = False
        etat = [None, None] # None: Pas trouvé, False: Ouvert, True: Ouvert et fermé.
        corres = {'(': 0, ')': 0, '[': 1, ']': 1}
     
        for c in chaine:
            if bloc:
    ## CHANGEMENTS-DEBUT ##
                if c in ')]':
                    if etat[corres[c]] is False: #Bonne correspondance
                        etat[corres[c]] = True
                        bloc = False
                    else: #Mauvaise correspondance
                        return False
                elif pattern_declaParam.match(c) is None: # Caractère non autorisé
                    return False
    ## CHANGEMENTS-FIN ##
     
            else:
                if c in '([':
                    if etat[corres[c]] is None: #Pas encore trouvé
                        etat[corres[c]] = False
                        bloc = True
                    else: #Déjà trouvé
                        return False
                elif c in '{=': #Fin du test, vérification de la fermeture
                    return (False not in etat)
                else:
                    return False
        return False
     
     
     
    # Tests divers
    if __name__ == '__main__':
        if True:
            tabloDeclaParam = []
    # OK
            tabloDeclaParam.append("{nyosnvygteonvyudsom")
            tabloDeclaParam.append("(12azER){nyosnvygteonvyudsom")
            tabloDeclaParam.append("(12azER=_;|)[12azER=_;|]{nyosnvygteonvyudsom")
            tabloDeclaParam.append("[12azER=_;|]{nyosnvygteonvyudsom")
     
            tabloDeclaParam.append("=nyosnvygteonvyudsom")
            tabloDeclaParam.append("(12azER)=nyosnvygteonvyudsom")
            tabloDeclaParam.append("(12azER=_;|)[12azER=_;|]=nyosnvygteonvyudsom")
            tabloDeclaParam.append("[12azER=_;|]=nyosnvygteonvyudsom")
    # PAS OK
            tabloDeclaParam.append("|nyosnvygteonvyudsom")
            tabloDeclaParam.append("(12a\"zER){nyosnvygteonvyudsom")
            tabloDeclaParam.append("(a=é)[12azER=_;|]{nyosnvygteonvyudsom")
            tabloDeclaParam.append("(a=r[12azER=_;|]{nyosnvygteonvyudsom")
            tabloDeclaParam.append("((12azER)=nyosnvygteonvyudsom")
     
            for decla in tabloDeclaParam:
                print decla + ' ===> ' + str(testMeth(decla))
                print '-'*60
    Un grand merci à tous !

    PS : pour clore ce post, je suis de moins en moins convaincu par les regex... Le seul endroit où j'en ai trouvé l'utilité c'est pour repérer des nombres romains : voir ici.

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

Discussions similaires

  1. Requete toute simple mais pas si simple
    Par rose0729 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 20/11/2012, 15h03
  2. SQL Oracle simple, mais pas pour moi
    Par Cyril75 dans le forum SQL
    Réponses: 2
    Dernier message: 24/02/2012, 16h19
  3. Un batch simple enfin pas pour moi
    Par Louis Griffont dans le forum Linux
    Réponses: 9
    Dernier message: 14/10/2009, 11h49
  4. Requête peut être simple, mais compliquée pour moi !
    Par xfree dans le forum Langage SQL
    Réponses: 11
    Dernier message: 17/08/2007, 16h09
  5. Question SQL (facile) mais pas pour moi
    Par fabianrs dans le forum Langage SQL
    Réponses: 15
    Dernier message: 30/03/2006, 03h44

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