Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Regex] Remplacer deux sous-chaines

Sujet résolu
    27 septembre 2012 à 16:51:45

    Bonjour,

    Mon problème, c'est que je n'arrive pas à remplacer deux sous_chaines en utilisant re.sub().

    Pour être plus clair, un exemple :

    re.sub(r'(a)(b)', '', 'abaaabbbaba')
    


    Qu'est-ce que je dois écrire comme 2ème argument pour pouvoir remplacer tous les a par des b et tous les b par des a ?
    • Partager sur Facebook
    • Partager sur Twitter
      27 septembre 2012 à 18:15:32

      Pas besoin de regex:

      >>> str.translate('abba', str.maketrans('ab', 'ba'))
      'baab'
      
      • Partager sur Facebook
      • Partager sur Twitter
        27 septembre 2012 à 18:17:51

        En fait, ce que j'ai donné, c'est juste un exemple, et ce que j'ai besoin de faire en vrai necéssite l'utilisation de regex.
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          27 septembre 2012 à 18:21:58

          Bonjour,

          Il doit y avoir mieux, mais il y a au moins ça:

          import re
          
          def remplacement(matchobj):
              car = matchobj.group(0)
              if car=="a":
                  return "b"
              elif car=="b":
                  return "a"
              else:
                  return car
          
          print re.sub(r'(a)|(b)', remplacement, 'abaaabbbaba')
          babbbaaabab
          
          • Partager sur Facebook
          • Partager sur Twitter
            27 septembre 2012 à 19:32:09

            Dans le même genre, en plus propre :

            http://www.daniweb.com/software-develo [...] n-text-python

            Mais ça ne réponds pas totalement à la problématique de départ : si le problème est réellement d'intervertir deux motifs d'expressions rationnelles, je ne pense pas que ça ait un sens (car les chaines matchées peuvent varier, et finalement tu remplace quoi par quoi ? suppose par exemple que seul l'un des 2 motifs est trouvé).
            Bref, je crois que la question de départ n'est pas bien définie et mérite éclaircissement.
            • Partager sur Facebook
            • Partager sur Twitter
              27 septembre 2012 à 21:20:03

              Bon, je crois vraiment que je me suis mal exprimé. Le but n'est pas d'intervertir, mais de remplacer le premier groupe de la regex par une chaine, et de remplacer le deuxième groupe de la regex par une autre chaine, le tout en un seul appel de la fonction sub, si possible.

              Pour l'instant, je crois que c'est impossible, sauf avec la technique de tyrtamos, mais s'il y a mieux, n'hésitez pas à poster :D
              • Partager sur Facebook
              • Partager sur Twitter
                28 septembre 2012 à 1:52:05

                Dans le même esprit, j'ai concocté ceci pour un truc un peu générique, mais je ne trouve pas ça beau :

                import re
                
                def replace_multi(s, dic):
                    reg = re.compile('('+')|('.join(dic)+')')
                    def repl(matchobj):
                        for n in range(reg.groups):
                            if matchobj.group(n+1) != None:
                                return list(dic.values())[n]
                        return matchobj.group(0)
                    return reg.sub(repl, s)
                


                >>> replace_multi('aabbabaab', {'a':'b', 'b':'a'})
                'bbaababba'
                >>> replace_multi('12 15 aa bb 16', {r'\d':'x', r'[^ ]':'*'})
                'xx xx ** ** xx'
                
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  28 septembre 2012 à 8:14:51

                  Bonjour,

                  Je pensais à une autre solution plus courte.

                  Elle nécessite que, en fonction du contexte, on identifie un caractère qui ne sera jamais présent dans la chaine, et dont on va se servir dans les substitutions. Par exemple un '@':

                  x = 'abaaabbbaba'
                  x = re.sub(r'ab', r'@', x)
                  x = re.sub(r'ba', r'ab', x)
                  x = re.sub(r'@', r'ba', x)
                  print x
                  babbbaaabab
                  


                  Qu'on peut, bien sûr, écrire en une seule ligne:

                  x = 'abaaabbbaba'
                  print re.sub(r'@', r'b', re.sub(r'b', r'a', re.sub(r'a', r'@', x)))
                  babbbaaabab
                  


                  Rien n'empêche de faire ça avec des chaines et non des caractères: "abcd" => "@", "defg" => "abcd", "@" => "defg"

                  • Partager sur Facebook
                  • Partager sur Twitter
                    28 septembre 2012 à 13:18:10

                    Citation : tyrtamos

                    Bonjour,

                    Je pensais à une autre solution plus courte.

                    Elle nécessite que, en fonction du contexte, on identifie un caractère qui ne sera jamais présent dans la chaine, et dont on va se servir dans les substitutions. Par exemple un '@':

                    x = 'abaaabbbaba'
                    x = re.sub(r'ab', r'@', x)
                    x = re.sub(r'ba', r'ab', x)
                    x = re.sub(r'@', r'ba', x)
                    print x
                    babbbaaabab
                    



                    Qu'on peut, bien sûr, écrire en une seule ligne:

                    x = 'abaaabbbaba'
                    print re.sub(r'@', r'b', re.sub(r'b', r'a', re.sub(r'a', r'@', x)))
                    babbbaaabab
                    



                    Rien n'empêche de faire ça avec des chaines et non des caractères: "abcd" => "@", "defg" => "abcd", "@" => "defg"



                    Je ne vois pas trop l'intérêt des caractères de substitution, vu que ce que tu a fais, on aurait pu le résumer à ça :

                    print re.sub(r'a', r'b', re.sub(r'b', r'a', x))
                    
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      28 septembre 2012 à 13:42:28

                      A mon avis, tu n'as pas exécuté ton dernier code qui donne: bbbbbbbbbbb

                      Et c'est pour ça qu'il faut un caractère intermédiaire.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        28 septembre 2012 à 14:26:57

                        Citation : tyrtamos

                        x = 'abaaabbbaba'
                        x = re.sub(r'ab', r'@', x)
                        x = re.sub(r'ba', r'ab', x)
                        x = re.sub(r'@', r'ba', x)
                        print x
                        babbbaaabab
                        

                        Il y a des fautes de frappe dans le code il me semble, la sortie ne correspond pas.


                        Sinon, cette méthode est couteuse car elle demande 3 appels à sub, et un remplacement inutile (pour remplacer uniquement 2 motifs, s'il y en a plus alors le nombre d'appels et de remplacement va encore augmenter). Et puis il n'est pas forcément évident de travailler avec un motif inutilisé (ça demande un minimum d'acquis sur les données, ou bien un traitement qui peut être couteux).

                        La méthode que j'ai proposée peut elle aussi s'avérer couteuse au niveau de la fonction repl, mais je pense que ça reste moins couteux au final.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          28 septembre 2012 à 14:43:59

                          Citation : yoch

                          Il y a des fautes de frappe dans le code il me semble, la sortie ne correspond pas.



                          Oui, absolument. J'avais fait des essais avec des chaines (et pas seulement des caractères) pour vérifier que ça marchait, et j'ai recopié ici le mauvais code. Le bon est, bien sûr:

                          x = re.sub(r'a', r'@', x)
                          x = re.sub(r'b', r'a', x)
                          x = re.sub(r'@', r'b', x)
                          


                          Sinon, ok pour la consommation de ressources... Quoique que quelquefois, on a des surprises en essayant.

                          Je préfère de toute façon la 1ère solution que j'ai donnée.
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            28 septembre 2012 à 14:49:22

                            Je ne comprend pas en quoi la proposition de cerium50 est fausse, si on pouvait m'expliquer ce que j'ai pas pigé :-°
                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 septembre 2012 à 15:22:51

                              Citation : fred1599

                              Je ne comprend pas en quoi la proposition de cerium50 est fausse, si on pouvait m'expliquer ce que j'ai pas pigé :-°


                              Simplement qu'on veut pouvoir remplacer des motifs décrits par des expressions régulières, et pas seulement des caractères (ou même des sous-chaines).
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                28 septembre 2012 à 15:26:51

                                Salut yoch,

                                Citation

                                Simplement qu'on veut pouvoir remplacer des motifs décrits par des expressions régulières, et pas seulement des caractères (ou même des sous-chaines).



                                J'avais un peu deviné cette réponse, mais le conseil de cerium50 me semblait correct, dans le sens où les regex ici et d'ailleurs dans ce post, me semble inutile.

                                Je voulais plutôt essayer de comprendre pourquoi les regex en fait.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  28 septembre 2012 à 16:09:40

                                  Salut,

                                  Citation : fred1599

                                  Je voulais plutôt essayer de comprendre pourquoi les regex en fait.


                                  Alors pour ça, c'est au PO de le justifier, et il est effectivement fort possible que ce ne soit pas indispensable...

                                  Mais sinon, la problématique en soi est intéressante, et ce indépendamment du langage.
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  [Regex] Remplacer deux sous-chaines

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown