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

Langage PHP Discussion :

Extraire une séquence


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2003
    Messages : 46
    Par défaut Extraire une séquence
    Bonjour tout le monde,


    Des sequences sont definies par des chaines de caracteres : 'abc1-3,7,10-14x2@@ext' est la definition textuelle de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    abc01ext
    abc02ext
    abc03ext
    abc07ext
    abc10ext
    abc12ext
    abc14ext
    Ces chaines sont de la forme [prefix][numeros][padding][suffix]

    Le nombre d'arobase definit le padding des index. Les x2, x3... le pas entre chaque index.

    J'utilise l'expression reguliere suivante pour separer mes chaines en 4 parties :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    r'''(?P<indices>(?:(?:-?[\d]+--?[\d]+(?:x\d+)?|-?[\d]+),?)*)
        (?P<padding>(?(indices)@*|@+))'''
    J'utilise a cet effet la function split du module re de python.

    Ca fonctionne bien avec de chaines comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    3
    3@@
    @@
    -10--6
    -10--6x2
    -10--6x2@@
    -10--6x2,-4,-1-1@@
    p.-10--6x2,-4,-1-1@@
    p.-10--6x2,-4,-1-1@@.s
    Cependant si ma chaine devient compliquee, ca marche beaucoup moins bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    '/tmp  files/foo2_v2,x2.0001.2-10#.-2.3-11@@._-10--6x2,-4,-1-1@@_bar-10--6x2,-4,-1-1@@.tar.bz'
    Dans ce cas la, le premier "2" est matche par le group (?<indices>), alors que c'est le dernier -10--6x2,-4,-1-1@@ qui devrait etre matche.

    J'essais d'eviter au maximum la manipulation des chaines de caracteres en dehors du traitement effectue par les expressions regulieres.

    Donc :
    - comment s'assurer que mon expression reguliere va matcher la derniere occurence ?
    - peut specifier une expression reguliere qui me permettrait de matcher directement le prefix et le suffixe sans passer par la function split ? Quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    (?P<prefix>.*?)
    (?P<indices>(?:(?:-?[\d]+--?[\d]+(?:x\d+)?|-?[\d]+),?)*)
    (?P<padding>(?(indices)@*|@+)
    (?P<suffix>.*)
    Bien evidement l'exemple ne fonctionne pas, le groupe (?P<prefix>.*) retourne une chaine vide.

    Merci beaucoup pour votre aide !

  2. #2
    Membre Expert
    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
    Par défaut
    Bonjour,



    Tu ne décris pas suffisamment les chaînes que tu veux détecter.
    Celles que tu donnes en exemple sont elles vraiment toutes celles que tu veux voir matcher avec la RE, pas plus et pas moins ? Ou est ce une présentation du problème avec progressivité ?

    3
    3@@
    @@
    -10--6
    -10--6x2
    -10--6x2@@
    -10--6x2,-4,-1-1@@
    p.-10--6x2,-4,-1-1@@
    p.-10--6x2,-4,-1-1@@.s
    Je m'étonne d'y voir 3 ou @@ tout seuls.



    En analysant la RE que tu donnes, on voit qu'elle définit un ensemble de chaînes matchantes potentielles bien plus large que ce dont rendent compte ces exemples.

    Ainsi, il n'y a pas dans tes exemples de premier nombre non précédé d'un tiret. Or la présence d'un tiret facultatif dans la RE

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    r'''(?P<indices>(?:(?:-?[\d]+--?[\d]+(?:x\d+)?|-?[\d]+),?)*)
        (?P<padding>(?(indices)@*|@+))'''
    fait qu'une chaîne telle que '10--6x2,-4,-1-1@@' matche elle aussi.

    Ce tiret participe à une parenthèse répétable dont le contenu doit rendre compte de tout ce qui est nombre au sein de la chaîne aussi. Je me demande donc si ce que tu as écrit pour l'intérieur de la chaîne ne se répercute pas par maladresse sur le premier nombre.



    Par ailleurs, il semble qu'il y ait un ordre de préséance dans l'organisation d'une chaîne matchante:
    --6 jamais avant le premier nombre
    --6x2 toujours avant d'autres nombres précédés d'une virgule
    les nombres successifs doivent ils avoir toujours un tiret devant eux ?
    @@ toujours à la fin


    Sur la base de ces observations , j'ai réécrit l'expression régulière pour éviter qu'un nombre seul soit capté.
    C'est en effet -?[\d]+ dans

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (?P<indices>(?:(?:-?[\d]+--?[\d]+(?:x\d+)?|-?[\d]+),?)*)
    qui en est responsable.

    Enfin bref, je n'arrive pas à comprendre totalement ta RE mais je propose la suivante. Dis moi si elle convient.
    J'ai tenu compte que dans la logique du split() que tu veux appliquer, il est nécessaire d'avoir une séparation entre une partie <indices> et une partie <padding>, bien qu'on pourrait écrire la RE autrement s'il n'y avait pas cette contrainte.

    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
    import re
     
    RE = '(?P<indices>(?:'\
                         '(?=@)'\
                         '|'\
                         '\d+(?=@)'\
                         '|'\
                         '-\d+(?:--\d+(?:x\d+(?:,?-\d+)*)?)?'\
                      ')'\
         ')'\
         '(?P<padding>@*)'
     
    pat = re.compile(RE)
     
    tu = ('3','3@@','@@','-45','-10--6','-10--6x2','-10--6x2@@',
                '-10--6x2,-4,-1-1@@','p.-10--6x2,-4,-1-1@@',
                'p.-10--6x2,-4,-1-1@@.s')
    for u in tu:
        print
        print u
        if pat.search(u):
            print pat.search(u).groups()
            print pat.split(u)
        else:
            print 'Pas de match'
     
    print '==========================================='
    ch = '/tmp  files/foo2_v2,x2.0001.2-10#.-2.3-11@@'\
         '._-10--6x2,-4,-1-1@@'\
         '_bar-10--6x2,-4,-1-1@@'\
         '.tar.bz'
    print ch
    print
    print pat.split(ch)
    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
    >>> 
     
    3
    Pas de match
     
    3@@
    ('3', '@@')
    ['', '3', '@@', '']
     
    @@
    ('', '@@')
    ['', '', '@@', '']
     
    -45
    ('-45', '')
    ['', '-45', '', '']
     
    -10--6
    ('-10--6', '')
    ['', '-10--6', '', '']
     
    -10--6x2
    ('-10--6x2', '')
    ['', '-10--6x2', '', '']
     
    -10--6x2@@
    ('-10--6x2', '@@')
    ['', '-10--6x2', '@@', '']
     
    -10--6x2,-4,-1-1@@
    ('-10--6x2,-4,-1-1', '@@')
    ['', '-10--6x2,-4,-1-1', '@@', '']
     
    p.-10--6x2,-4,-1-1@@
    ('-10--6x2,-4,-1-1', '@@')
    ['p.', '-10--6x2,-4,-1-1', '@@', '']
     
    p.-10--6x2,-4,-1-1@@.s
    ('-10--6x2,-4,-1-1', '@@')
    ['p.', '-10--6x2,-4,-1-1', '@@', '.s']
    ===========================================
    /tmp  files/foo2_v2,x2.0001.2-10#.-2.3-11@@._-10--6x2,-4,-1-1@@_bar-10--6x2,-4,-1-1@@.tar.bz
     
    ['/tmp  files/foo2_v2,x2.0001.2', '-10', '', '#.', '-2', '', '.3', '-11', '@@', '._', '-10--6x2,-4,-1-1', '@@', '_bar', '-10--6x2,-4,-1-1', '@@', '.tar.bz']
    >>>


    Cette RE a donc l'air de marcher. Il n'y a qu'une chose avec quoi elle ne matche pas: un nombre seul. C'est voulu parce que je ne vois pas en quoi un nombre seul peut être une information d'après ce que tu as expliqué. Dis moi si je me trompe.

    Remarque l'élément (?=@) dans la RE: il définit un match de largeur nulle, c'est bien pratique.






    Pour capter la dernière occurence, je propose:
    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
    import re
     
    RE = '(?P<indices>(?:'\
                         '(?=@)'\
                         '|'\
                         '\d+(?=@)'\
                         '|'\
                         '-\d+(?:--\d+(?:x\d+(?:,?-\d+)*)?)?'\
                      ')'\
         ')'\
         '(?P<padding>@*)'
     
    pat = re.compile(RE)
     
    ch = '/tmp  files/foo2_v2,x2.0001.2-10#.-2.3-11@@'\
         '._-10--6x2,-4,-1-1@@'\
         '_bar-10--6x2,-4,-1-1@@'\
         '.tar.bz'
    print ch
    print
    print pat.findall(ch)[-1]
    ou bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for m in pat.finditer(ch):
        pass
    print m.groups()



    Pour extraire directement les 4 éléments d'une définition textuelle, il faudrait en savoir un peu plus sur les valeurs que peuvent avoir les préfixes et les suffixes.

    S'ils sont de longueur 3 comme le donne à penser ton exemple, on peut faire tourner les codes ci-dessus avec la RE suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    RE = '(.{3})(?P<indices>(?:'\
                         '(?=@)'\
                         '|'\
                         '\d+(?=@)'\
                         '|'\
                         '-\d+(?:--\d+(?:x\d+(?:,?-\d+)*)?)?'\
              '))'\
         '(?P<padding>@*)(.{3})'

    Selon la nature des préfixes et suffixes, on peut imaginer des tas d'autres moyens.
    Par exemple si les préfixes peuvent prendre leurs valeurs dans deux listes connues de valeurs, on peut faire:
    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
    import re
     
    prefixes = ['rubu','dadaou','whist','meduy']
    suffixes = ['abc','123','xyz','ext','blong']
     
    RE = ('('+'|'.join(prefixes)+')'
          '(?P<indices>(?:(?=@)'
          '|'
          '\d+(?=@)'
          '|'
          '-\d+(?:--\d+(?:x\d+(?:,?-\d+)*)?)?'
          '))'
          '(?P<padding>@*)'
          '('+'|'.join(suffixes)+')')
     
    print RE
     
    pat = re.compile(RE)
     
    ch = '/tmp  files/foo2_v2,x2.0001.2-10#.-2.3-11@@'\
         '._-10--6x2,-4,-1-1@@'\
         '_barubu-10--6x2,-4,-1-1@@'\
         'exterieur'
     
    print pat.findall(ch)[-1]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (rubu|dadaou|whist|meduy)(?P<indices>(?:(?=@)|\d+(?=@)|-\d+(?:--\d+(?:x\d+(?:,?-\d+)*)?)?))(?P<padding>@*)(abc|123|xyz|ext|blong)
     
    ('rubu', '-10--6x2,-4,-1-1', '@@', 'ext')



    À mon avis, tu n'as pas besoin de la fonction split() . Les groupes capturés de chaque match se trouvent dans groups() et la fonction group() permet aussi de faire des manipulations étonnantes et hyper-utiles sans difficulté.

Discussions similaires

  1. [WD18] Comment extraire une séquence video dans le champ Multimédia ?
    Par vegetacherif dans le forum WinDev
    Réponses: 1
    Dernier message: 13/06/2015, 15h49
  2. Extraire une séquence entre 2 patterns
    Par jhfra dans le forum Shell et commandes GNU
    Réponses: 10
    Dernier message: 16/01/2014, 15h10
  3. extraire une séquence d'une image 3D
    Par jeune ingénieure dans le forum Images
    Réponses: 4
    Dernier message: 01/07/2012, 10h57
  4. Extraire une séquence d'octets d'un fichier
    Par benito9253 dans le forum Windows Forms
    Réponses: 0
    Dernier message: 23/12/2009, 22h26
  5. Extraire une séquence d'un fichier MPEG
    Par enzosp dans le forum DirectX
    Réponses: 2
    Dernier message: 24/02/2003, 11h30

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