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 :

Expression régulière pour "éclater" (split) une chaîne


Sujet :

Langage Delphi

  1. #1
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut Expression régulière pour "éclater" (split) une chaîne
    Bonjour,

    depuis l'apparition de FMX et plus de TMaskedit j'utilise de plus en plus les expressions régulières (une nouvelle marotte )
    cette fois ci je voudrais exploiter une chaine de caractères bien particulière pour extraire 3 groupes il y a bien sur d'autres méthodes ( à coup de pos, copy et delete) mais je me suis dit que puisque regex il y avait pourquoi ne pas tester.

    Pour faire simple soit une chaine *ACASTELO-220360 je veux obtenir les groupes ACASTELO, 220, 360
    sachant que le * peut aussi être un ? et que le tiret est obligatoire et qu'il y a 6 chiffres ensuite (pour l'instant en tout cas)

    j'ai construit mon expression ainsi
    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
    var
       modele,assort,point : String;
       UneExpression : TRegEx;
       UnEnsemble : TMatch;
    begin
        UneExpression:=TRegEx.Create('[*?](.{1,15}){1}[-](\d{3}){1}(\d{3}){1}',[]);
        if UneExpression.IsMatch(Saisie.Text) then
             begin
                     UnEnsemble:=UneExpression.Match(saisie.Text);
                      Modele:=UnEnsemble.Groups.Item[1].Value;
                      Assort:=UnEnsemble.Groups.Item[2].Value;
                      Point:=UnEnsemble.Groups.Item[3].Value;
             end 
             else  showmessage('erreur'); 
    end;
    ce qui fonctionne ! (ça c'est pour répondre à une discussion lorsque j'ai recherché sur le forum)
    cependant et c'est là ma question j'ai été incapable d'utiliser Split plutôt que Match , ce qui m'aurait semblé plus commode je ne vois pas comment 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
     
    var
       modele,assort,point : String;
       UneExpression : TRegEx;
       MonSplit : TArray<String>;
    begin
        UneExpression:=TRegEx.Create('[*?](.{1,15}){1}[-](\d{3}){1}(\d{3}){1}',[]);
        if UneExpression.IsMatch(Saisie.Text) then
             begin
                   MonSplit:=UneExpression.Split(saisie.Text);
                   Modele:= ? 
                   Assort:= ?
                   Point:= ?  
             end
             else showmessage('erreur'); 
    end;
    en fait je n'obtiens dans mon tableau via le Split que : '','360','' et je me demande où je foire
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Bonsoir !

    Citation Envoyé par SergioMaster Voir le message
    j'utilise de plus en plus les expressions régulières (une nouvelle marotte )
    Ah tiens, toi aussi ?

    Une petite remarque : ton expression contient des choses superflues, n'est-ce pas ? On pourrait se contenter de '[*?](.{1,15})-(\d{3})(\d{3})'.

    Autrement, je ne crois pas que la méthode Split puisse te servir dans ce cas, puisque tu n'as pas de séparateur entre tes chiffres. Voici un exemple qui montre à quoi peut servir la méthode Split :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    uses
      RegularExpressions,
      SysUtils;
     
    var
      a: TArray<string>;
      s: string;
     
    begin
      a := TRegEx.Split(GetEnvironmentVariable('PATH'), ';');
     
      for s in a do
        WriteLn(s);
    end.
    L'expression régulière (dans mon exemple un simple caractère) représente l'ensemble des séparateurs.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  3. #3
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Roland Chastain Voir le message
    Ah tiens, toi aussi ?
    quand j'arriverais à totalement les maitriser ça sera nickel, c'est surtout la seule chose que j'ai trouvée pour pallier "les masques de saisie" avec FMX

    Une petite remarque : ton expression contient des choses superflues, n'est-ce pas ? On pourrait se contenter de '[*?](.{1,15})-(\d{3})(\d{3})'.
    tiens, je ne connaissais pas la balise CODEINLINE et effectivement mon expression est "améliorable" je voulais être sur qu'il n'y ait à chaque fois qu'un groupe obligatoire, j'ai donc insisté dessus
    Autrement, je ne crois pas que la méthode Split puisse te servir dans ce cas, puisque tu n'as pas de séparateur entre tes chiffres
    merci pour le code , ce Split est si peu documenté que j'en croyais l'usage plus "extensif" (récupération des groupes de l'expression)
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  4. #4
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Bonjour SergioMaster

    Juste une remarque, qui n'est a mon avis pas très importante car ta recherche est dans une petite chaîne et pas très complexe mais il me semble que IsMatch va lancer la recherche puis après le Match va refaire cette même recherche.
    Je pense que le IsMatch existe juste pour savoir si une correspondance est trouvée (sans se soucier de récupérer les groupes etc). En gros pour la vérification de l'existence ou le la cohérence d'une chaîne.

    Toi tu veux récupérer le contenu donc autant aller directement dans le vif du sujet

    J'aurai donc plutôt écrit

    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
    var
      modele,assort,point : String;
      UneExpression : TRegEx;
      UnEnsemble    : TMatch;
    begin
      UneExpression := TRegEx.Create('[*?](.{1,15})-(\d{3})(\d{3})',[]);
      UnEnsemble := UneExpression.Match(saisie.Text);
      if UnEnsemble.Success then
      begin
        Modele := UnEnsemble.Groups[1].Value;
        Assort := UnEnsemble.Groups[2].Value;
        Point  := UnEnsemble.Groups[3].Value;
      end
      else showmessage('erreur');
    end;

  5. #5
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je ne connaissais pas le if UnEnsemble.Success thence qui effectivement est encore mieux

    merci Barbibulle

    ceci étant l'expression va peut être évolué pour en faire un "soit un code barre EAN13 soit mon expression"
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  6. #6
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    ceci étant l'expression va peut-être évoluer pour en faire un "soit un code barre EAN13 soit mon expression"
    Est-ce que tu pourrais donner un échantillon des chaînes à traiter (pour le plaisir de l'exercice) ?
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  7. #7
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Est-ce que tu pourrais donner un échantillon des chaînes à traiter (pour le plaisir de l'exercice) ?
    ce n'est pas encore défini en totalité mais tu as déjà :
    1 - un code EAN13 ou un code 2/5 entrelacé (13 chiffres)
    2 - la chaine telle que déjà indiquée
    3- une référence commande sous la forme SAISON-NUMERO-LIGNE ou saison est sur 5 caractères (en exemple H2015,2015H OP15E ... ) ,numéro et ligne se passe de commentaire

    le but serait alors de savoir quelle saisie a été faite pour ensuite l'exploiter.

    Je le répète il est facile de tester le 1 avant le 2 puis de tester le 3 (avec mon ancien programme D3 c'est ce que je fait), mais j'aimerais savoir si l'utilisation d'expression régulière permettrait de tout combiner (pour le plaisir de l'exercice justement )
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    j'aimerais savoir si l'utilisation d'expression régulière permettrait de tout combiner
    Oui, ce serait intéressant d'essayer. Peut-être avec des "named groups" ?
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  9. #9
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Je crois que le moteur de regex utilisé par delphi est le moteur open source PCRE. Vous pourrez connaître toutes ces possibilités à cette adresse: http://pcre.org/original/pcre.txt.

    Barbibule a donné la bonne méthode. Inutile de vérifier si l'expression réussie pour ensuite recommencer avec la même expression pour extraire. C'est vrai que c'est un peu contre-intuitif quand on a pris l'habitude de toujours vérifier l'existence d'une donnée ou d'une condition.

    Utiliser la méthode Split serait possible avec [^0-9A-Z]|(?=[0-9]{3}$) (tout caractère n'étant pas une lettre ou un chiffre, ou à la position suivie de trois chiffres avant la fin) mais elle a deux défauts:
    • Elle se contente de séparer la chaîne, mais à aucun moment le format de la chaîne n'est vérifié. C'est donc le loto en ce qui concerne le nombre et la nature des items produits, ce qui implique toute une batterie de tests pour pouvoir les exploiter.
    • Le caractère de séparation * ou ? se trouvant en début de chaîne, Split produira une chaîne vide comme premier item.


    Tu peux encore améliorer l'expression en supprimant le point qui est très (trop) permissif en le remplaçant par une classe de caractères qui exclut le tiret [^-]{1,15} ou plus explicite [A-Z]{1,15}. Ainsi tu éviteras au moteur de regex de devoir faire machine arrière (le mécanisme de backtracking: .{1,15} prendra 15 caractères car les quantificateurs sont gourmands (greedy) par défaut et le moteur devra "rendre" les caractères un à un jusqu'à tomber sur un tiret).

    Autre chose, la méthode Match réussie si une occurrence est trouvée (et rend disponible les résultats de celle ci), mais cette occurrence peut se trouver n'importe où dans la chaîne. Pour s'assurer que cette occurrence commence au début de la chaîne et se termine à la fin de la chaîne, il faut utiliser les ancres de début et de fin de chaîne (\A et \z ou ^ et $, mais attention avec ces dernières dont le sens peut changer avec l'utilisation du modificateur m (multiline)).

    Attention également avec les raccourcis de classe de caractères comme \d, (\w, \s, etc.) qui peuvent être interprétés selon la table ascii (i.e. [0-9] ou son synonyme POSIX [[:digit:]]) ou selon la table unicode (incluant de ce fait tous les chiffres des différents alphabets). Il est évident que la 2e possibilité procure un surcroît de travail inutile au moteur. J'ignore quelles sont les options par défaut de PCRE pour delphi, mais il suffit de tester si \d matches les chiffres en arabe par exemple pour le savoir.

    Ce qui donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UneExpression := TRegEx.Create('\A[*?]([A-Z]{1,15})-([0-9]{3})([0-9]{3})\z',[]);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  10. #10
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour et merci @CosmoKnacki pour ces infos supplémentaires

    j'en arrive à cette expression

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    \A[*?](?<Modele>[^-]{1,15}){1}[-](?<Assort>\d{3}){1}(?<Point>\d{3}){1}\z|\A(?<EAN>123\d{10})\z|\A(?<DeuxdeCinq>\d{13})\z
    avec les groupes nommés (note pour l'EAN je n'ai bien sûr pas donné le préfixe exact )
    reste à savoir comment Delphi gère les noms de groupes (s'il les gère) ce sera l'objet de mon [Edit] ou du prochain post si quelqu'un fait un ajout
    pour l'instant j'utilise Expresso pour m'aider dans la rédaction de ces expressions mais si quelqu'un à la piste d'un bon tutoriel / livre (j'avoue ne pas avoir eu le temps de chercher ne serait-ce que dans le forum Perl) je suis preneur
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  11. #11
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Bonjour !

    Pardon d'insister, mais tu n'as toujours pas donné d'échantillon sur lequel on puisse travailler !

    Oui, Delphi gère les groupes nommés. Je n'ai pas l'exemple sous la main mais je peux le retrouver d'ici ce soir.

    Pour le tutoriel : Regular expressions
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  12. #12
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    @Roland voilà un exemple

    pour les curieux , les articles sont des articles de mode : chaussures/textiles, assortiment veut dire couleur et pointure fait bien sur référence à la taille et pour tout dire oui ce sont des codes barres qui sont scannés le plus souvent, saisis manuellement de temps en temps le * ou ? indiquant s'il s'agit d'un produit standard ou , luxe, d'un produit spécifique client. Pour l'instant les spécifiques n'ont pas de codes barres EAN ou 2of5 cependant cela pourrait bien changé certains clients nous imposant déjà leurs codes barres EAN et leur format d'étiquettes il est également envisageable que le préfixe ne soit pas "fixe" ce qui va compliquer les choses! cependant ces articles étant bien particuliers l'opérateur sait qu'il s'agit d'articles clients et indique donc la marque (client, je tairai les noms) correspondante avant

    *ABORG-001360 << articles
    ?CASTELO 1419-002370
    *EX/MINOU1424-412380
    *RUBAN-003001
    1234578011230 << EAN
    3760162052329 << un vrai EAN dans ce cas le préfixe est 376
    1456441001360 << 2of5
    // quelques "faux"
    AAAAAAA
    *AAAAA-001
    *AAAAAA001360
    123121212
    l'EAN est un faux dans le sens où je n'ai pas donné le bon préfixe et me suis pas amusé à calculer la nouvelle clé, si on utilise alors le préfixe 376016 à la place de mon 123 alors la deuxième sera considéré comme un 2of5

    @Roland comme tu le constateras pas de trucs particuliers pour les tests
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  13. #13
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Comme l'a souligné CosmoKnacki une chose qui a sont importance également c'est de savoir si tu veux analyser une chaîne qui contient un ensemble de code ou bien ta chaîne ne contient qu'un seul code à analyser ?

    Si c'est un ensemble, question bis : sont ils tous en début de ligne ?

  14. #14
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    non ce n'est qu'un seul code à chaque fois (dans ce cas)
    c'est en fait une zone de saisie (TEdit) généralement l'entrée se fera par une douchette USB, le onKeyPress testant le #13 pour passer au traitement (onExit) via un SelectNext du contrôle
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  15. #15
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Fort instructif cet exercice !

    Ma conclusion (pour aujourd'hui du moins), c'est 1° qu'il serait plus simple d'utiliser trois expressions séparées et 2° qu'il n'y a pas grand avantage à utiliser des groupes nommés.

    La variable de type TGroup a une propriété Success mais soit elle vaut "True" et on ne peut en tirer aucune conclusion, soit le programme se plante lorsqu'on teste la valeur de cette propriété !

    Voici la façon de faire que j'ai trouvée (code testé avec XE2 et XE10) :

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    {$APPTYPE CONSOLE}
     
    uses
      RegularExpressions, SysUtils;
     
    const
      SAMPLE: array[0..10] of string = (
        '*ABORG-001360', // articles
        '?CASTELO 1419-002370',
        '*EX/MINOU1424-412380',
        '*RUBAN-003001',
        '1234578011230', // EAN
        '3760162052329', // un vrai EAN dans ce cas le préfixe est 376
        '1456441001360', // 2of5
        // quelques "faux"
        'AAAAAAA',
        '*AAAAA-001',
        '*AAAAAA001360',
        '123121212'
      );
    const
      PATTERN = '[*?](?<nom1>[^-]{1,15})-(?<nom2>\d{3})(?<nom3>\d{3})|(?<nom4>123\d{10})|(?<nom5>\d{13})';
     
    var
      g: TGroup;
      e: TRegEx;
      m: TMatch;
      i: integer;
     
    procedure ShowResult(aGroupName: string);
    begin
      WriteLn(Format('  %s = "%s"', [aGroupName, m.Groups[aGroupName].Value]));
    end;
     
    begin
      e := TRegEx.Create(PATTERN);
     
      for i := Low(SAMPLE) to High(SAMPLE) do
      begin
        WriteLn('SAMPLE[', i, ']');
        m := e.Match(SAMPLE[i]);
        if m.Success then
        begin
          if m.Groups['nom1'].Value <> '' then
          begin
            ShowResult('nom1');
            ShowResult('nom2');
            ShowResult('nom3');
          end else
            if m.Groups['nom4'].Value <> '' then
              ShowResult('nom4')
            else
              ShowResult('nom5');
        end;
      end;
     
      ReadLn;
    end.
    SAMPLE[0]
    nom1 = "ABORG"
    nom2 = "001"
    nom3 = "360"
    SAMPLE[1]
    nom1 = "CASTELO 1419"
    nom2 = "002"
    nom3 = "370"
    SAMPLE[2]
    nom1 = "EX/MINOU1424"
    nom2 = "412"
    nom3 = "380"
    SAMPLE[3]
    nom1 = "RUBAN"
    nom2 = "003"
    nom3 = "001"
    SAMPLE[4]
    nom4 = "1234578011230"
    SAMPLE[5]
    nom5 = "3760162052329"
    SAMPLE[6]
    nom5 = "1456441001360"
    SAMPLE[7]
    SAMPLE[8]
    SAMPLE[9]
    SAMPLE[10]
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  16. #16
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Roland Chastain Voir le message
    Fort instructif cet exercice !
    heureux que ça plaise
    Ma conclusion (pour aujourd'hui du moins), c'est 1° qu'il serait plus simple d'utiliser trois expressions séparées et 2° qu'il n'y a pas grand avantage à utiliser des groupes nommés.
    c'est pour l'instant le cas, en fait je fais un test sur le fait que le texte puisse être transformé en nombre pour écarter EAN et 2of5 avant de 'parser' si ce n'est pas le cas (donc une seule expression)
    La variable de type TGroup a une propriété Success mais soit elle vaut "True" et on ne peut en tirer aucune conclusion, soit le programme se plante lorsqu'on teste la valeur de cette propriété !
    voilà qui n'arrange pas les affaires
    Voici la façon de faire que j'ai trouvée (code testé avec XE2 et XE10) :
    je vais étudier ce code avec attention (après les urgences qui m'attendent comme tous les matins )
    si effectivement les noms de groupe sont plus un frein qu'autre chose cela allègera l'expression, j'en profiterai quand même pour tenter de vérifier les temps entre l'utilisation d'expression et une extraction manuelle (celle du bon vieux temps )
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  17. #17
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    non ce n'est qu'un seul code à chaque fois (dans ce cas)
    c'est en fait une zone de saisie (TEdit) généralement l'entrée se fera par une douchette USB, le onKeyPress testant le #13 pour passer au traitement (onExit) via un SelectNext du contrôle
    Dans ce cas il est judicieux de le préciser dans ton expression.

    Pour éviter que :"AAAAAA001360?CASTELO 1419-002370" te réponde que le code est trouvé....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var
      modele,assort,point : String;
      UneExpression : TRegEx;
      UnEnsemble    : TMatch;
    begin
      UneExpression := TRegEx.Create('^[*|?](.{1,15})-(\d{3})(\d{3})',[]);
      UnEnsemble := UneExpression.Match(Edit1.Text);
      if UnEnsemble.Success then
      begin
        Modele := UnEnsemble.Groups[1].Value;
        Assort := UnEnsemble.Groups[2].Value;
        Point  := UnEnsemble.Groups[3].Value;
      end
      else showmessage('erreur');

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    *ABORG-001360 => ABORG | 001 | 360
    *ACASTELO-220360 => ACASTELO | 220 | 360
    ?CASTELO 1419-002370 => CASTELO 1419 | 002 | 370
    *EX/MINOU1424-412380 => EX/MINOU1424 | 412 | 380
    *RUBAN-003001 => RUBAN | 003 | 001
    1234578011230 => Erreur
    3760162052329  => Erreur
    1456441001360  => Erreur
    AAAAAAA => Erreur
    *AAAAA-001 => Erreur
    *AAAAAA001360 => Erreur
    123121212 => Erreur
    Cette expression n'exclus pas les codes :
    *?AAAAA-123456 => ?AAAAA | 123 | 456
    Si Modèle ne peux pas débuter par * ou ? il est possible d'exclure ces caractères du premier groupe ainsi le code ci dessus serait rejeté.

  18. #18
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour
    Citation Envoyé par Barbibulle Voir le message
    Dans ce cas il est judicieux de le préciser dans ton expression.
    cela a été précisé depuis suite à la remarque de CosmoKnacki. Le \A est équivalent à ^ ?
    Cette expression n'exclus pas les codes :
    *?AAAAA-123456 => ?AAAAA | 123 | 456
    Si Modèle ne peux pas débuter par * ou ? il est possible d'exclure ces caractères du premier groupe ainsi le code ci dessus serait rejeté.
    je n'avais pas prévu ce cas normalement impossible (mais allez faire confiance à un utilisateur )
    N.B. un contrôle d'existence modèle/assortiment/pointure (ce que j'appelle un article) est ensuite fait de toute façon, mais si la saisie est rejetée c'est encore mieux

    l'expression devient alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '\A[*?](?<Modele>[^-*?]{1,15}){1}[-](?<Assort>\d{3}){1}(?<Point>\d{3}){1}\z'
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  19. #19
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    La variable de type TGroup a une propriété Success mais soit elle vaut "True" et on ne peut en tirer aucune conclusion, soit le programme se plante lorsqu'on teste la valeur de cette propriété !
    Par contre on peut regarder le nombre de groupe de la collection et en déduire lequel a été trouvé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        if m.Success then
          case m.Groups.Count of
             4 :begin
                  ShowResult('nom1');
                  ShowResult('nom2');
                  ShowResult('nom3');
                end;
             5 :  ShowResult('nom4');
             6 :  ShowResult('nom5');
          end;

  20. #20
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Barbibulle Voir le message
    Par contre on peut regarder le nombre de groupe de la collection et en déduire lequel a été trouvé.
    Bien vu !
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 4
    Dernier message: 14/11/2008, 21h00
  2. Expression régulière pour récupérer une chaîne.
    Par z980x dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 24/06/2007, 15h01
  3. Réponses: 22
    Dernier message: 18/07/2006, 15h05

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