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 :

Besoin d'aide pour écrire une regex


Sujet :

Python

  1. #1
    Futur Membre du Club
    Inscrit en
    Juillet 2007
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 9
    Points : 9
    Points
    9
    Par défaut Besoin d'aide pour écrire une regex
    Bonjour,

    J'aurais besoin d'un petit coup de main pour écrire une regex pour la fonction re.split. Le but est de splitter la chaîne sur et uniquement sur les espaces, sauf si ceux-ci sont dans une chaîne qui serait entre quotes ou doubles quotes.

    Par exemple :
    test test2 test3 "test 4 test 5" :
    ["test", "test2", "test3", "test 4 test 5"]

    test test2=test3 test4="test 5" :
    ["test", "test2=test3", 'test4="test 5"']

    Je suis vraiment une buse en expression régulière, et jusque là je ne suis arrivé à rien

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Salut,

    Bienvenue dans le forum.

    Ceci a l'air de marcher:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import re
     
    pat = re.compile('(([^ "\']+)|((["\'])(.+?)(?(4)\\4)))+')
     
    for u in ('''test test2 test3 "test 4 test 5"''',
              '''test test2=test3 test4="test 5"''',
              '''   test   test2   test3    "test 4 test 5" ''',
              '''   test    test2=test3    test4="test 5"   ''',
              '''"test 4 test 5" test4="test 5"''',
              '''  "  test 4 test 5" "test    6  test      7"''',
              """  '  "  soleil  colombe  clafoutis " mer" =tuile" ' test12 test13'ko ala'""",
              ''''sau ci ss on' plaket "   orange' ' banane' zozo'== = taga'da"'''):
        print '\n{{{'+u+'}}}'
        print [ m.group() for m in pat.finditer(u) ]

    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
    {{{test test2 test3 "test 4 test 5"}}}
    ['test', 'test2', 'test3', '"test 4 test 5"']
     
    {{{test test2=test3 test4="test 5"}}}
    ['test', 'test2=test3', 'test4="test 5"']
     
    {{{   test   test2   test3    "test 4 test 5" }}}
    ['test', 'test2', 'test3', '"test 4 test 5"']
     
    {{{   test    test2=test3    test4="test 5"   }}}
    ['test', 'test2=test3', 'test4="test 5"']
     
    {{{"test 4 test 5" test4="test 5"}}}
    ['"test 4 test 5"', 'test4="test 5"']
     
    {{{  "  test 4 test 5" "test    6  test      7"}}}
    ['"  test 4 test 5"', '"test    6  test      7"']
     
    {{{  '  "  soleil  colombe  clafoutis " mer" =tuile" ' test12 test13'ko ala'}}}
    ['\'  "  soleil  colombe  clafoutis " mer" =tuile" \'', 'test12', "test13'ko ala'"]
     
    {{{'sau ci ss on' plaket "   orange' ' banane' zozo'== = taga'da"}}}
    ["'sau ci ss on'", 'plaket', '"   orange\' \' banane\' zozo\'== = taga\'da"']

  3. #3
    Futur Membre du Club
    Inscrit en
    Juillet 2007
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 9
    Points : 9
    Points
    9
    Par défaut
    Merci beaucoup ! Je viens de tester, ça a l'air de répondre exactement à mes besoins.

    Merci !

    Edit : par contre, j'ai beau lire et relire le pattern, je ne le comprends. Quelqu'un aurait 2 minutes pour me le détailler / expliquer SVP ?

  4. #4
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    - Quand on écrit un motif ':+' , on dit au moteur de regex:
    tant que tu trouves des caractères ':' se succédant les uns après les autres, tu les agrèges et tu me renvoie leur succession.


    - Quand on écrit un motif [ae]+ , on dit au moteur de regex:
    tant que tu trouves des caractèes 'a' OU 'e' se succédant de façon jointive, tu les collectionne et tu m'en sors la succession quand tu arrives au bout.

    [...] symbolise UN caractère dans la chaîne explorée, mais ce caractère peut être de différentes valeurs si bien que [...] définit une classe de caractères matchant à UNE position. Il faut lire tous les caractères se trouvant entre deux crochets [...] comme s'ils étaient séparés par le signe du OU logique: '|'


    - Et quand on veut que le OU soit entre, non pas des caractères uniques, mais des séquences, on écrit un motif contenant explicitement le OU sous forme d'une barre verticale '|' (une fois ou plusieurs fois) séparant des sous-motifs pour attraper les diverses sous-chaînes que le moteur de regex doit détecter dans la chaîne explorer:

    (seq1)|(seq2)|(?:seq3)|(seq4)
    Dans cette RE, le troisième groupe est rendu non capturant par '?:' placé en tête.



    --------------------------------------------------------------

    Ma RE exprime une alternative entre deux types de séquences:



    ([^ "\']+) attrape toutes les séquences n'étant formé d'aucun des trois caractères suivants: le blanc, l'apostrophe ' , le quote "

    C'est le ^ qui spécifie que l'ensemble de caractères est défini par complémentation.

    Ceci attrape toutes les séquences normales du genre test2, test4=





    ((["\'])(.+?)(?(4)\\4)) attrape toutes les séquences qui commencent par ' ou "

    ' ou " s'exprime par ["\'] On est obligé de mettre un antislash devant ' parce que ' est le délimiteur de la RE.




    La parenthèse ouvrante de (["\']) est la 4ième parenthèse ouvrante dans la RE ==> cette parenthèse et sa collègue fermante définissent le groupe 4.

    Dans une regex, \4 est ce qu'on appelle une référence arrière qui signifie: à cet endroit remplacer \4 par la valeur trouvée en amont comme groupe 4.
    Quand je dis «Dans une regex,» , je désigne un objet REGEX.

    Le problème étant de spécifier à cet objet au moyen d'une chaîne la succession de deux caractères: antislash 4

    En effet, l'antislash est le caractère d'échappement dans les chaînes. '\4' signifie donc : échappe le 4.

    Pour obtenir non pas cette signification mais 'antislah suivi de 4', il faut échapper l'antislash devant le 4. pour cela.... il faut un antislash devant l'antislash !

    Avec deux antislashes dans la RE (RE = une chaîne), la regex (regex = objet REGEX) va bien comprendre '\\4' comme 1 antislash suivi de 4.




    Ensuite, la notation (?(4)X) est une assertion conditionnelle:

    Elle dit que doit se trouver dans la chaîne explorée à l'endroit correspondant à sa position dans la RE le caractère ou séquence X à condition que le groupe 4 existe, c'est à dire n'est pas None

    Dans la RE, j'ai mis \\4 comme X ce qui signifie que quand la regex aura trouvé une apostrophe ' ou une quote " en tête , elle devra trouver l'identique en clôture du groupe qu'elle capturera.






    Enfin on colle toutes les séquences bleues qui sont trouvés jointives
    '(([^ "\']+) |((["\'])(.+?)(?(4)\\4)))+'

    Ce qui fait d'ailleurs que ça marche aussi quand il y a plus de 2 séquences bleues à la suite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import re
     
    pat = re.compile('(([^ "\']+)|((["\'])(.+?)(?(4)\\4)))+')
    ch = '''test  "test 4 test 5"test'plusieurs'titi"'violine'hu"  cameleon'''
    li = [ m.group() for m in pat.finditer(ch) ]
    print li
    print "\\" in li[1]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ['test', '"test 4 test 5"test\'plusieurs\'titi"\'violine\'hu"', 'cameleon']
    False

    L'instruction print "\\" in li[1] est pour montrer qu'il n'y a pas d'antislash dans le résultat.

    Les antislashes qui apparaissent en affichage sont destinés à mettre en évidence que les apostriphes qui les suivent ne sont pas des délimiteurs de la chaîne affichée.

  5. #5
    Futur Membre du Club
    Inscrit en
    Juillet 2007
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 9
    Points : 9
    Points
    9
    Par défaut
    Pfiou !

    Merci beaucoup pour toutes ces explications ! Je vais étudier tout ça avec attention !

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

Discussions similaires

  1. [RegEx] Besoin d'aide pour construire une regex complexe
    Par Predax dans le forum Langage
    Réponses: 2
    Dernier message: 06/03/2013, 08h52
  2. Besoin d'aide pour écrire une requête SQL
    Par tompintures dans le forum Requêtes
    Réponses: 2
    Dernier message: 31/01/2011, 10h47
  3. Besoin d'aide pour écrire une requête
    Par Jean-Marc68 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 23/10/2009, 19h54
  4. [RegEx] Besoin d'un coup de main pour écrire une regex
    Par gaboo_bl dans le forum Langage
    Réponses: 7
    Dernier message: 18/08/2006, 17h53
  5. besoin d'aide pour intégrer une entité dans un MCD
    Par barkleyfr dans le forum Schéma
    Réponses: 17
    Dernier message: 13/10/2005, 13h29

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