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 Delphi Discussion :

Regex et remplacement


Sujet :

Langage Delphi

  1. #1
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut Regex et remplacement
    Bonjour

    Je ne sais pas si c'est possible avec le TRegEX de Delphi (10.3) mais peut-être que vous pourrez m'éclairer.

    Je veux remplacer dans le code source de mon appli une fonction BDE par son équivalent Firedac.

    Base.GetTableNames(Tables); doit être remplacé par Base.GetTableNames('', Base.Params.Database, '', Tables);

    Voilà mon code et le résultat correct :

    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
     
    procedure TFormMain.btnTestsClick(Sender: TObject);
    var
      NomCompo, Centre, Liste, Fin: string;
      Match                       : TMatch;
      Reg4                        : TRegEx;
    begin
      Reg4 := TRegEx.Create('(?<NomCompo>\w*)(?<Centre>\.GetTableNames\()(?<Liste>\w*)(?<Fin>\);)',
        [TRegExOption.roIgnoreCase]);
      Match    := Reg4.Match('Base.GetTableNames(Tables);');
      NomCompo := Match.Groups['NomCompo'].Value;
      Centre   := Match.Groups['Centre'].Value;
      Liste    := Match.Groups['Liste'].Value;
      Fin      := Match.Groups['Fin'].Value;
     
      Log(NomCompo);
      Log(Centre);
      Log(Liste);
      Log(Fin);
     
      Log(Format('%s%s%s%s%s%s%s%s',
        [NomCompo,
         Centre,
         #39#39', ',
         NomCompo,
         '.Params.Database',
         ', '#39#39', ',
         Liste,
          ');']));
    end;
    Résultat

    Base
    .GetTableNames(
    Tables
    );
    Base.GetTableNames('', Base.Params.Database, '', Tables);
    Tout fonctionne et je pourrais me contenter de ça.

    Mais comme je suis curieux (trop peut-être) je me dis que le TRegEx doit pouvoir faire ça en utilisant les groupes nommés que je récupère.
    Sauf que ma curiosité est en train de me filer la migraine parce que je ne vois pas comment utiliser ça.

    Est-ce que l'une ou l'un d'entre vous saurait me montrer (si c'est possible) la façon de faire ?

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 268
    Points : 41 671
    Points
    41 671
    Billets dans le blog
    64
    Par défaut
    Casse-tête intéressant.
    J'ai lu que l'on pouvait se référer aux groupes par des ($0 for whole match, $Number for captured groups, ${Name} for named capturing groups)
    mais de là à établir un replace, pas facile
    Expresso
    serait un bon ami pour tester

    Nom : Capture.PNG
Affichages : 154
Taille : 32,6 Ko

    avec un texte de remplacement (incomplet)
    Nom : Capture.PNG
Affichages : 157
Taille : 27,1 Ko

    mais est-ce que cela fonctionnera avec RegEx de Delphi ?

  3. #3
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    j'utilise expresso aussi et le site regex101

    Mais la question est justement de le faire avec Delphi :-)

  4. #4
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    Effectivement avec noms de groupe on y arrive

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       Log( Reg4.Replace('Base.GetTableNames(Tables);',
         '${NomCompo}${Centre}'#39#39', ${NomCompo}.Params.Database, '#39#39', ${Liste});'));
    Base
    .GetTableNames(
    Tables
    );
    Base.GetTableNames('', Base.Params.Database, '', Tables);
    Base.GetTableNames('', Base.Params.Database, '', Tables);
    Merci de m'avoir indiqué la bonne direction

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Pour info sans groupe nommé : ((\w+)\.GetTableNames\()(\w+(\);)) et $1'', $2.Params.Database, '', $3

  6. #6
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    C'est plus court mais moins parlant je trouve.
    Mais oui, ça fait la même chose. Juste une question de goût :-)

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    mais est-ce que cela fonctionnera avec RegEx de Delphi ?
    Sans penser substitution et toujours pour info, regular-expressions.info permet de contrôler si une construction est valide pour un langage, dont Delphi, en le sélectionnant dans une des deux listes déroulantes.

  8. #8
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    Intéressant et effectivement très utile

  9. #9
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 910
    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 910
    Points : 6 703
    Points
    6 703
    Par défaut
    Si tu veux du parlant les groupes de captures nommés sont une bonne idée, mais c'est pas une raison pour en mettre partout: tous les éléments "fixes" de la chaîne n'ont pas besoin d'être capturés, et tu peux les réécrire tels quels dans la chaîne de remplacement.
    Mieux encore tu peux éviter que les parties fixes situées au début et à la fin n'aient besoin d'être réécrites en les éliminants du match:
    Code pattern : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (?<NomCompo>\w+) \Q.GetTableNames(\E \K
    (?<Liste>\w+) (?= \); )
    (avec l'option roIgnorePatternSpace)
    Code remplacement : Sélectionner tout - Visualiser dans une fenêtre à part
    '', ${NomCompo}.Params.Database, '', ${Liste}

    demo

    Le \K élimine du résultat tout ce qui est à sa gauche (ce qui n'empêche pas la capture NomCompo), (?= ... ) est un test avant qui lui ne consomme pas de caractères, donc ); n'est pas inclus dans le match non plus.

    Résultat, tu obtiens un combo pattern/remplacement qui ne s'attaque qu'à la partie concernée: les paramètres.

  10. #10
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    Si tu veux du parlant les groupes de captures nommés sont une bonne idée, mais c'est pas une raison pour en mettre partout: tous les éléments "fixes" de la chaîne n'ont pas besoin d'être capturés, et tu peux les réécrire tels quels dans la chaîne de remplacement.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      Texte, Pattern: string;
    begin
      Texte   := '  Base.GetTableNames(Liste);';
      Pattern := '(?<NomCompo>\w+)\.GetTableNames(\K(?<Liste>\w+))(?=\));';
      Regx := TRegEx.Create(Pattern, [TRegExOption.roIgnoreCase, TRegExOption.roIgnorePatternSpace]);
    J'essaye mais je dois pas être assez doué :-(
    Ça ne fonctionne pas. A vrai dire, j'ai pas tout compris

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    CosmoKnacki a utilisé /Q /E. Ce qui se trouve entre ces balises est une chaîne littérale, le point sera traité comme tel et les parenthèses aussi. Tu les as supprimées ! Dès lors la parenthèse après GetTableNames doit être échappée \(.

    (?=...) est un positive lookahead : un contrôle que le symbole en traitement est suivi d'un motif bien précis. Ce contrôle ne fait cependant pas avancer le curseur (le motif recherché/trouvé n'est pas "consommé" dans le jargon), il se trouve toujours sur le dernier caractère de liste.

    Liste est bien suivi d'une parenthèse fermante, jusque là tout va bien, mais au prochain pas on va effectivement traiter cette parenthèse et là ça coince puisque dans ton motif tu aimerais un ; !

    Il faut donc inclure ce point-virgule dans le lookahead, ce qui donnera (?<NomCompo>\w+)\.GetTableNames\(\K(?<Liste>\w+)(?=\);).

    roIgnorePatternSpace n'est pas nécessaire et permet d' "aérer" le motif par des espaces pour plus de clarté. Dans ce cas les espaces éventuellement recherchés devraient être échappés.


    regex101 met à disposition un debugger (en bas à gauche). Très instructif pour comprendre le cheminement, ce qu'il trouve et où est positionné le curseur.

  12. #12
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 502
    Points : 3 133
    Points
    3 133
    Par défaut
    Merci pour ces explications complémentaires !
    J'ai essayé hier soir mais ça a été un échec.
    Ce matin, l'esprit plus clair, ça va mieux.

    Je ne connaissais pas cet \K qui est bien pratique.
    Pour le LookAHead, j'avoue constater que ça fonctionne mais bon, avec un peu de pratique je devrais pouvoir ajouter ça à mes connaissances.

    Encore merci à tous pour votre aide !

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

Discussions similaires

  1. regex et remplacement
    Par mmaura dans le forum C
    Réponses: 1
    Dernier message: 16/08/2007, 20h15
  2. [RegEx] regex pour remplacer bbcode et img
    Par gwena54 dans le forum Langage
    Réponses: 6
    Dernier message: 16/08/2007, 15h42
  3. Utiliser Regex pour remplacement
    Par soveste dans le forum Collection et Stream
    Réponses: 13
    Dernier message: 19/03/2007, 10h48
  4. [Notepad++] utiliser regex pour remplacer des caractères
    Par ilood dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 04/02/2007, 05h06
  5. regex.h remplacement ?
    Par seal3 dans le forum C++
    Réponses: 4
    Dernier message: 25/08/2005, 00h07

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