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 :

Regex modification du dernier caractère trouvé


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut Regex modification du dernier caractère trouvé
    Bonjour à tous, je suis actuellement en train de développer un script qui me permettra de convertir des documents Latex en HTML.
    Je rencontre malheureusement un léger souci, pour modifier mes balises Latex en HTML j'utilise le module "re" et des regex.
    Mon problème est le suivant lorsque deux balises sont imbriquées \underline{textbf{text souligné et en gras}} par exemple.
    J'arrive à modifier \underline{ en <u> mais lorsque je veux modifier le dernier } impossible à chaque fois c'est le premier qui est modifié...
    Pouvez-vous m'aider ?

  2. #2
    Membre éprouvé Avatar de olivier1969
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Novembre 2013
    Messages
    153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 153
    Par défaut
    Bonjour,

    Tu peux faire voir la partie de ton code qui traite ça stp ?

  3. #3
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    voilà ce que j'ai fait

    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
    # fonction qui change les balise "\emph" -> "<i>"
    def make_emph(emph):
        reg_emph = r"\\emph{"
        emph_tex = re.compile(reg_emph)
        # change les balise "\emph{" -> "<i>"
        emph = re.sub(emph_tex, r"<i>", emph, count=1)
        # change le prochain "}"
        emph = re.sub(r"}", r"</i>", emph, count=1)
        return emph
     
     
    def make_textbf(textbf):
        reg_textbf = r"\\textbf{"
        textbf_tex = re.compile(reg_textbf)
        textbf = re.sub(textbf_tex, r"<strong>", textbf, count=1)
        textbf = re.sub(r"}", r"</strong>", textbf, count=1)
        # renvoie le texte modifie
        return textbf

    voilà, quand ma ligne correspond à \textbf{text en gras}" c'est fonctionnel, même chose avec \emph,
    mais quand j'ai \emph{\textbf{text en gras et italique}} les deux balises de fin sont inversées

  4. #4
    Membre éprouvé Avatar de olivier1969
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Novembre 2013
    Messages
    153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 153
    Par défaut
    Bonjour ,

    Ce qui est normal , tu traites la première balise <i> donc tu remplace le premier } par </i> tu auras donc </i>} ; puis en traitant la deuxième tu va remplacer le deuxième } et tu auras </i></strong>

    Le problème , c'est que tu ne gères pas l'imbrication de balises -> la dernière à s'ouvrir est aussi la première à se fermer ....

  5. #5
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    Citation Envoyé par olivier1969 Voir le message
    Bonjour ,

    Ce qui est normal , tu traites la première balise <i> donc tu remplace le premier } par </i> tu auras donc </i>} ; puis en traitant la deuxième tu va remplacer le deuxième } et tu auras </i></strong>

    Le problème , c'est que tu ne gères pas l'imbrication de balises -> la dernière à s'ouvrir est aussi la première à se fermer ....
    Oui, je comprend bien mais est-il possible de "passer" une des "}" et de modifier seulement la deuxième ou celle voulu ?

  6. #6
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par xfitgit Voir le message
    \underline{textbf{text souligné et en gras}}
    c'est typiquement pour pallier à ce genre de difficulté qu'on préfère utiliser un analyseur syntaxique en bonne et due forme plutôt que des regexps

    par ailleurs, une requête goog type "python latex to html" semble donner un certain nombre de résultats potentiellement pertinents

  7. #7
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    salut,



    c'est typiquement pour pallier à ce genre de difficulté qu'on préfère utiliser un analyseur syntaxique en bonne et due forme plutôt que des regexps

    par ailleurs, une requête goog type "python latex to html" semble donner un certain nombre de résultats potentiellement pertinents
    D'accord je ne connaissais pas je vais regarder de ce côté merci !

  8. #8
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Citation Envoyé par xfitgit Voir le message
    Mon problème est le suivant lorsque deux balises sont imbriquées \underline{textbf{text souligné et en gras}} par exemple.
    J'arrive à modifier \underline{ en <u> mais lorsque je veux modifier le dernier } impossible à chaque fois c'est le premier qui est modifié...
    Ce n'est pas possible. Pour atteindre la bonne accolade fermante quelque soit le niveau d'imbrication avec une regex, il faut construire une pattern récursive, or le module re ne propose pas cette fonctionnalité. Il existe bien un module regex alternatif qui le propose (pypi/regex), mais tu peux faire sans en adoptant une stratégie très simple: remplacer les balises imbriquées en premier (les balises n'en contenant pas d'autres) et ainsi de suite, jusqu'à ce qu'il n'y ait plus rien à remplacer.

  9. #9
    Membre éprouvé Avatar de olivier1969
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Novembre 2013
    Messages
    153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 153
    Par défaut
    De mémoire j'avais fait un truc dans le genre pour un format de fichier spécifique avec des '[ ]' ; en alimentant un dico d = {1 : '</u>', 2 : '</strong>'} à chaque fois que tu ouvres une balise , et dès que tu la fermes tu prends l'index le plus grand et tu le supprimes etc etc

  10. #10
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    Citation Envoyé par olivier1969 Voir le message
    De mémoire j'avais fait un truc dans le genre pour un format de fichier spécifique avec des '[ ]' ; en alimentant un dico d = {1 : '</u>', 2 : '</strong>'} à chaque fois que tu ouvres une balise , et dès que tu la fermes tu prends l'index le plus grand et tu le supprimes etc etc
    Reprend moi si j'ai mal compris mais en gros, je cherche mes balises en parcourant la ligne je la remplace par son équivalent -> je stock la balise de fin dans un dico
    Une fois que je n'ai plus rien je remplace les "}" par ce qu'il y a dans le dico ?

  11. #11
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Ce n'est pas possible. Pour atteindre la bonne accolade fermante quelque soit le niveau d'imbrication avec une regex, il faut construire une pattern récursive, or le module re ne propose pas cette fonctionnalité. Il existe bien un module regex alternatif qui le propose (pypi/regex), mais tu peux faire sans en adoptant une stratégie très simple: remplacer les balises imbriquées en premier (les balises n'en contenant pas d'autres) et ainsi de suite, jusqu'à ce qu'il n'y ait plus rien à remplacer.
    Donc faire un regex qui trouve des balises non imbriquées (donc ou il n'y a pas de '{' avant) c'est pas tellement le problème mais il faut quand même que je modifie une balise qui est à une certaine position, donc pas possible ?

  12. #12
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    un exemple au pied levé d'analyse récursive à coups de regexps :
    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
    import re
     
    def parse(text):
        trans = {'textbf': 'B', 'textit': 'I', 'underline': 'U'}
        matches = re.match(r'^\s*(textbf|textit|underline)\s*\{(.+)\s*\}', text, re.DOTALL)
        return '<{0}>{1}</{0}>'.format(trans[matches.group(1)], parse(matches.group(2))) if matches else text
     
    print(parse('''
    textit {
     
        underline {
            underline{ underline{textit   {
                        underline{textbf{pouet}}    } }
            }}
        }
     
    '''))
    et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <I><U><U><U><I><U><B>pouet</B></U></I></U></U></U></I>

  13. #13
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    j'essaie avec et je vous tiens au courant merci de votre aide!

  14. #14
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Citation Envoyé par xfitgit Voir le message
    Donc faire un regex qui trouve des balises non imbriquées (donc ou il n'y a pas de '{' avant) c'est pas tellement le problème mais il faut quand même que je modifie une balise qui est à une certaine position, donc pas possible ?
    Si, c'est possible, l'idée est justement de remplacer les balises qui n'en contiennent pas d'autres puis de recommencer jusqu'à ce qu'il n'y en ait plus. De cette manière on évacue tout ce qui est récursivité. La position des balises n'a aucune importance.

    Une exemple:
    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
    import re
     
    s = r'''\underline{\textbf{text souligné et en gras}}
            \textbf{\underline{text en gras et souligné}}'''
     
    pat = re.compile(r'''
        \\ (?P<tag> \w+ ) { (?P<content> [^\\{}]* (?: \\. [^\\{}]* )* ) }
    ''', re.DOTALL | re.VERBOSE);
     
    corr = { 'underline': 'u', 'textbf': 'b', 'textit': 'i' }
     
    def replacement(m):
        return '<{0}>{1}</{0}>'.format(corr[m.group('tag')], m.group('content'))
     
    n = 1
     
    while n:
        s, n = pat.subn(replacement, s)
     
    print(s)
    L'avantage c'est que le principe est simple et que c'est torché en même pas 20 lignes, l'inconvénient c'est que du point de vue algorithmique c'est pas spécialement finaud et qu'une nouvelle chaîne est créée à chaque passage dans la boucle while (le nombre de passages est égal au niveau d'imbrication maximum dans la chaîne plus un).

  15. #15
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Une autre méthode qui consiste à "tokenizer" la chaîne en tag d'ouverture, accolade de fermeture, et contenu, en utilisant re.finditer et en s'aidant d'une pile pour savoir à qui appartient l'accolade de fermeture. On empile le tag html correspondant lorsque le token est un tag d'ouverture et on le dépile lorsque le token est une accolade fermante. La chaîne sujet n'est donc parcourue qu'une seule fois, et on concatène au fur et à mesure le contenu adéquate à la chaîne du résultat:
    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
    import re
     
    s = r'''\underline{\textbf{text souligné et en gras}}
            \textbf{\underline{text en gras et souligné}}'''
     
    pat = re.compile(r'''
        (?P<open> \\ (?P<tag> \w+ ) { ) |
        (?P<close> } ) |
        (?P<content> [^\\{}]* (?: \\. [^\\{}]* )* )
    ''', re.DOTALL | re.VERBOSE)
     
    corr = { 'underline': 'u', 'textbf': 'b', 'textit': 'i' }
     
    result = ''
    stack = []
     
    for m in pat.finditer(s):
        if m.group('open'):
            tag = corr[m.group('tag')]
            stack.append(tag)
            result += '<{}>'.format(tag)
        elif m.group('close'):
            if stack:
                result += '</{}>'.format(stack.pop())
            else:
                result += '}'
        else:
            result += m.group('content')
     
    print(result)

  16. #16
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Décembre 2019
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Décembre 2019
    Messages : 10
    Par défaut
    [QUOTE=CosmoKnacki;11473376]Une autre méthode qui consiste à "tokenizer" la chaîne en tag d'ouverture, accolade de fermeture, et contenu, en utilisant re.finditer et en s'aidant d'une pile pour savoir à qui appartient l'accolade de fermeture. On empile le tag html correspondant lorsque le token est un tag d'ouverture et on le dépile lorsque le token est une accolade fermante. La chaîne sujet n'est donc parcourue qu'une seule fois, et on concatène au fur et à mesure le contenu adéquate à la chaîne du résultat:[code]import re

    C'est ce qui me semble le mieux dans mon cas je vais essayer !

Discussions similaires

  1. Réponses: 11
    Dernier message: 31/08/2014, 11h01
  2. [C#] Remplacer le dernier caractères (REGEX)
    Par aurelien.tournier dans le forum C#
    Réponses: 2
    Dernier message: 23/10/2006, 14h59
  3. Dernier caractère d'un char
    Par mindwind dans le forum Langage SQL
    Réponses: 3
    Dernier message: 01/12/2005, 13h57
  4. débarrasser un string de son dernier caractère ?
    Par fakinou dans le forum Langage
    Réponses: 27
    Dernier message: 28/09/2005, 21h58
  5. [ORDER BY]tri sur le dernier caractère d'un champ
    Par Tan dans le forum Langage SQL
    Réponses: 3
    Dernier message: 03/05/2004, 14h39

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