Partage
  • Partager sur Facebook
  • Partager sur Twitter

Expressions régulières

    21 novembre 2017 à 0:17:10

    Bonsoir,

    Je vois le cour de gbdiver sur le c++ moderne et j'en suis aux expressions régulières.

    Je croyais avoir bien compris le principe jusqu'à ce que je tombe sur cet exemple qui me laisse comme un c.. , si je peux me permettre

    {
            std::regex pattern("([a-zA-Z]+) \\1");    
            std::string replacement = "$1";     
            std::string target = "The cat cat bites the dog dog.";
            std::string output_str = regex_replace(target, pattern, replacement);
            std::cout << output_str << std::endl;
        }

    Ce qu'il affiche est  " The cat bites the dog."

    Par quel miracle saute-t-il les mots doublés?

    Il prend chaque lettre si il y en a 1 ou +  si j'ai bien compris. Mais quand s’arrête le groupe de capture, quand est-ce qu'il recommence, d’où viennent les espaces...

    Je suis perdu. o_O



    -
    Edité par lio2609 21 novembre 2017 à 12:42:50

    • Partager sur Facebook
    • Partager sur Twitter
    " Ce n'est pas parce qu'ils sont beaucoup à avoir tort qu'ils ont raison . "
      21 novembre 2017 à 1:05:00

      En réalité il ne saute pas les mots doublés, mais captures 2 mots identiques qui se suivent.

      (...) permet de capture quelque chose et \\1 correspond à la capture numéro 1.

      En gros, la regex dit: on prend un mot, un espace et le même mot que précédemment. Le tout sera remplacé par $1 qui correspond à la capture 1 dans la fonction de remplacement. Résultat, regex_replace prend 2 mots identiques et le remplace par le premier (donc supprime le second).

      Note qu'avec format_sed, on pourrait avoir \\1 pour la capture et le remplacement.

      En réalité, tous les doublons ne sont pas supprimés puisque que la regex fonctionne par paire.

      • dog dog -> dog
      • dog dog dog -> dog dog
      • dog dog dog dog -> dog dog
      • dog dog dog dog dog -> dog dog dog

      Pour véritablement supprimer les séquences de mots identiques:

      • pattern = "([a-zA-Z]+) (?=\\1)"
      • replacement = "" (rien)

      http://en.cppreference.com/w/cpp/regex/ecmascript#Assertions

      -
      Edité par jo_link_noir 21 novembre 2017 à 1:06:43

      • Partager sur Facebook
      • Partager sur Twitter
        21 novembre 2017 à 13:04:01

        Merci beaucoup pour ta réponse,

        J'ai maintenant compris le principe mais je ne comprends toujours pas comment la syntaxe de cette regex le produit.

        "[a-zA-Z]" : n'importe quelle lettre min ou maj ( ne vaut que pour une seule lettre ? )

        "([a-zA-Z]+)" : n'importe quelle lettre min ou maj si il en existe 1 ou plus et on prend tout ça en capture ? ( on s’arrête aux espace ? Si non on va jusqu'au bout de la phrase ?! )

        "\\1" : sert a dire que ce qu'il y a entre parenthèse peut être rappeler par "$1" ? ( donc toute la phrase ? Sinon pourquoi "cat" puis "dog" ?)

        :euh:

        • Partager sur Facebook
        • Partager sur Twitter
        " Ce n'est pas parce qu'ils sont beaucoup à avoir tort qu'ils ont raison . "
          21 novembre 2017 à 21:35:19

          > "[a-zA-Z]" : n'importe quelle lettre min ou maj ( ne vaut que pour une seule lettre ? )

          Oui

          "([a-zA-Z]+)" : n'importe quelle lettre min ou maj si il en existe 1 ou plus et on prend tout ça en capture ? (

          Oui

          > on s’arrête aux espace ? Si non on va jusqu'au bout de la phrase ?! )

          On s'arrête quand il n'y plus de correspondance. Donc, quand différent de lettre min ou maj.

          Mais regex_replace fait une boucle jusqu'à ne plus pouvoir rien remplacer.

          • Si à partir d'un caractère la regex ne correspond a rien, alors on passe au caractère suivant
          • Si à partir d'un caractère la regex correspond à quelque chose, alors on fait un remplacement et on continue la recherche depuis la fin de la correspondance.

          > "\1" : sert a dire que ce qu'il y a entre parenthèse peut être rappeler par "$1" ?

          Non. Ce sont 2 choses différentes qui font référence à une capture (ce qu'il y a entre parenthèse).

          \1 dans la regex indique que le pattern doit ajouter "dynamiquement" un morceau de texte dans la recherche, celui présent dans la capture 1.

          $1 dans le texte de remplacement s'applique après que le passage de la regex pour remplacer la correspondance de la regex (càd mot, espace, le même mot) par la capture 1 (càd. mot).

          • Partager sur Facebook
          • Partager sur Twitter
            22 novembre 2017 à 15:28:55

            Merci beaucoup pour le temps passé à me répondre, mais je suis un lent, ça risque donc d'être long:honte:

            Donc, dans ce cas ci :

            A quel moment la regex dit qu'elle prend [un mot, un espace puis un mot] ?

            Moi je vois ( on est bien d'accord que je vois flou :D ) :

            "([a-zA-Z]+)" Je prends le premier mot puisqu'il n'y a plus de correspondance avec l'espace , je le copie dans output_str , je recommence avec le mot suivant etc etc .

            Ce qui rendrait la même phrase sans les espaces... Ce qui n'est manifestement pas le cas...

            Je nage. >_<

            • Partager sur Facebook
            • Partager sur Twitter
            " Ce n'est pas parce qu'ils sont beaucoup à avoir tort qu'ils ont raison . "
              22 novembre 2017 à 17:21:45

              > A quel moment la regex dit qu'elle prend [un mot, un espace puis un mot] ? Moi je vois "([a-zA-Z]+)"

              Il faut prendre la regex dans son ensemble: "([a-zA-Z]+) \\1".

              Je te montre un exemple étape par étape du fonctionnement de regex_replace

              • v: position de début de correspondance
              • ^: position du curseur de recherche en cours
              • out: chaîne de résultat
                  v
                  a b b c
                  ^
                  out = ""
                  état = "([a-zA-Z]+)"
              

              L'"état" trouve des caractères, on avance le curseur de recherche. La capture 1 contient a.

                  v
                  a b b c
                   ^
                  out = ""
                  état = " "
              

              Espace trouvé, on avance

                  v
                  a b b c
                    ^
                  out = ""
              

              Échec de la correspondance, on est sur b on attend a. On déplace le caractère de début de correspondance dans out puis on reprend avec le caractère suivant.

                   v
                  a b b c
                   ^
                  out = "a"
                  état = "([a-zA-Z]+)"
              

              " " ne correspond pas, on fait pareil qu'à l'étape précédente.

                    v
                  a b b c
                    ^
                  out = "a "
                  état = "([a-zA-Z]+)"
              

              On trouve un mot (b, \1 correspond maintenant à b)

                    v
                  a b b c
                     ^
                  out = "a "
                  état = " "
              

              espace trouvé, on avance le curseur de recherche

                    v
                  a b b c
                      ^
                  out = "a "
                  état = " "
              

              On trouve b qui correspond à \1. La regex est "complète", on fait un remplacement de "b b" par "$1" qui correspond à la capture 1 est donc á "b"

                       v
                  a b b c
                       ^
                  out = "a b"
                  état = "([a-zA-Z]+)"
              

              Etc.

              • Partager sur Facebook
              • Partager sur Twitter
                22 novembre 2017 à 17:54:32

                Magnifique! Je crois avoir compris o_O .

                Si on transpose ça à notre phrase , ca veut dire que  "([a-zA-Z]+)" met toute une série de lettres dans la capture 1 jusqu'à ce qu'elle tombe sur autre chose qu'une lettre ( dans notre cas un espace).

                Puis compare la prochaine suite de lettres ( capture 2 ? ) avec capture 1 :

                Si != elle envoi la capture 1 dans out et reprend le test à la capture 2 (qui devient donc la 1) etc

                Si == elle envoi la capture 1 dans out et reprend le test après la capture 2.

                C'est bien ça?

                • Partager sur Facebook
                • Partager sur Twitter
                " Ce n'est pas parce qu'ils sont beaucoup à avoir tort qu'ils ont raison . "
                  22 novembre 2017 à 17:55:16 - Message modéré pour le motif suivant : Message complètement hors sujet


                    22 novembre 2017 à 23:27:35

                    > Si on transpose ça à notre phrase , ca veut dire que "([a-zA-Z]+)" met toute une série de lettres dans la capture 1 jusqu'à ce qu'elle tombe sur autre chose qu'une lettre ( dans notre cas un espace).

                    Oui

                    > Puis compare la prochaine suite de lettres ( capture 2 ? ) avec capture 1 :

                    Les captures 1 à n font uniquement référence aux parenthèses. Une paire de parenthèse = une capture.

                    Il y a aussi la capture 0 qui fait référence au texte complet qui correspond à la regex. C'est la partie qui va être remplacé par regex_replace.

                    > Si != elle envoi la capture 1 dans out et reprend le test à la capture 2 (qui devient donc la 1) etc

                    Pas tout à fait. On ne peut pas sauter un groupe de lettre est dire « on a trouvé abcd dans abcd ef, mais le reste ne correspond pas alors on reprend depuis l'espace. » Parce qu'avec une regex un peu plus complexe bcd ef peut avoir une correspondance (ex: ([a-z]+) \\1|bcd). Du coup, quel que soit le nombre de caractère traversé avant un échec, on avance toujours de 1 seul caractère.

                    Ceci explique pourquoi "abc bc" est remplacé par "abc". abc ne fonctionne pas, mais bc si.

                    -
                    Edité par jo_link_noir 23 novembre 2017 à 22:59:04

                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 novembre 2017 à 18:37:05

                      ok, merci beaucoup pour ton aide.

                      Il va me falloir beaucoup d'exercices pour assimiler ça mais je crois que j'ai compris, grâce à toi.

                      :magicien:

                      • Partager sur Facebook
                      • Partager sur Twitter
                      " Ce n'est pas parce qu'ils sont beaucoup à avoir tort qu'ils ont raison . "

                      Expressions régulières

                      × 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