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

ma regexp n'accepte pas les espaces


Sujet :

Langage PHP

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut ma regexp n'accepte pas les espaces
    Bonjour,

    ma regexp : #\A[\w\-(),ÈÉÁÑÓÖÉÍÚĆŽŠ&\/. \'"]*\z#.
    J'y ai mis plein de caractères accentués à cause des différentes langues (d'ailleurs, y en a certains que le forum ne connait pas). Ca passe bien, par contre, bien que j'ai mis un espace dedans, ça me signale une erreur avec le nom d'un chinois : SI YUAN.

    Mon code PHP :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     public function validString($string):bool
        {
            $pattern = '#\A[\w\-(),ÈÉÁÑÓÖÉÍÚĆŽŠ&\/. \'"]*\z#';
     
            $ret2 = preg_match($pattern, $string);
            return ($ret2 != 0) ;
        }
    Pourtant, si je teste avec https://regex101.com/, c'est bon.

    Qu'est-ce qu'il faut faire SVP ?

  2. #2
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Je m'en suis sorti avec :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $string = str_replace($string,' ','_');
    $pattern = '#\A[\w\-(),ÈÉÁÑÓÖÉÍÚĆŽŠ&\/. \'"]*\z#'; 
     
     
    $ret2 = preg_match($pattern, $string);
    mais c'est bizarre. Si vous avez une explication...

  3. #3
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    Peut-être que ce que tu crois être un espace (le caractère U+0020 SPACE) dans ta classe de caractères ou dans la chaîne que tu testes, n'en est pas un. Un peu comme une certaine boisson gazeuse, ça ressemble à un espace, ça a la couleur d'un espace, mais ce n'est pas un espace. Plusieurs caractères lui ressemblent comme le cadratin et ses divisions, l'espace fine (le mot "espace" est féminin, lorsqu'on parle typographie), ou encore l'espace insécable. La plupart d'entre eux sont indissociables à l'œil nu ou pour des non-experts (tout ceux qui n'ont pas travaillé dans l'imprimerie), et pourtant, bien utilisé, c'est ce genre de "petits riens typographiques" qui au final laisse une impression même à un béotien, c'est magique.

    Si ma théorie est juste, les trois quarts du temps il s'agit de l'espace insécable car c'est le plus couramment utilisé. On a vite fait de l'introduire dans un code avec un copier/coller. Tente d'effacer l'espace de ta classe de caractères pour le retaper.

    Si tu veux choper tout type d'espace horizontal dans une regex, tu disposes de la classe de caractères \h. Tu peux la placer dans ta classe de caractères ou bien t'en servir pour sanitizer la chaîne avant de la tester: $str = preg_replace('~\h+~u', ' ', $str);.




    À propos de ta pattern:

    Bon choix pour les ancres de début et fin de pattern \A et \z. Pas d'ambiguïté, droit au but.

    Le modificateur u: Dés lors que tu utilises des caractères en dehors de la table ASCII (comme les caractères accentués ou la faucille et le marteau), pour éviter toute ambiguïté, tu dois utiliser absolument le modificateur u en fin de pattern. Exemple, j'ai la classe de caractères suivante: [ÀŒ] composée de U+00C0 LATIN CAPITAL LETTER A WITH GRAVE encodé en utf8 avec les octets C3 et 80, et U+0152 LATIN CAPITAL LIGATURE OE encodé sur C5 et 92. Sans le modificateur u, C3 et 80 ne sont pas vu comme une séquence représentant le caractère À et uniquement dans cet ordre, mais comme des octets sans aucun liens qui peuvent être pris séparément dans n'importe quel ordre si on ajoute un quantificateur.
    Donc concrètement sans le modificateur u, [ÀŒ]+ matchera de manière inattendue le caractère Ò U+00D2 LATIN CAPITAL LETTER O WITH GRAVE encodé sur C3 et 92, en utilisant le C3 de À et le 92 de Œ.
    Avec le modificateur u, ce n'est plus possible car C3 et 80 sont bien identifiés comme faisant partie d'une séquence représentant le caractère À, idem avec C5 et 92 pour Œ, et ces octets ne peuvent plus être pris de manière indépendante pour constituer d'autres combinaisons correspondant à d'autres caractères.

    Les classes de caractères unicode: lorsque tu te retrouves à lister tous les caractères accentués possibles et imaginables, tu as une autre solution, c'est la classe de caractères unicode prédéfinie \p{Latin} qui les contient tous (ainsi que les non-accentués). Regarde le site https://www.utf8-chartable.de/unicode-utf8-table.pl pour te faire une idée (tout ce qui commence par LATIN en fait partie). Ça peut être une bonne option sauf si tu souhaites en exclure, et la ça dépend de ta sélection.

    Si tu es amené à écrire une classe de caractères assez longue, il est possible depuis PHP 7.3 d'utiliser le modificateur inline xx qui comme son cousin le modificateur x ne tient pas compte des caractères blanc dans la pattern, mais en plus ignore aussi les caractères blancs dans les classes de caractères. Ce qui permet ça par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $pattern = '~(?xx) \A [ - & / , . \' " ( ) _  \h  A-Z  Á È É Í Ñ Ó Ö É  Š Ú Ž ]*  \z ~u';
    Tous les espaces de la pattern sont ignorés mais les caractères blancs horizontaux sont représentés dans la pattern avec \h. Avec ce modificateur, pour signifier un espace, il suffit de l'échapper.




    Pour connaître les octets qui constituent une chaîne de caractères, il suffit de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for ($i = 0; $i < strlen($str); $i++) {
        echo strtoupper(dechex(ord($str[$i]))), ' ';
    }

  4. #4
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    j'ai essayé de suivre tes indications, mais j'ai le mot opus qui ne matche pas avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      public function validString($string):bool
        {
            $pattern = '#(?xx)\A[\w \- ( ) , È É Á Ñ Ó Ö É Í Ú Ć Ž Š & \h \/ . \' "]*\z u#';
     
            $ret2 = preg_match($pattern, $string);
            return ($ret2 != 0) ;
        }
    Quel est le problème, STP ? (dans le cas du mot opus, on pourrait bien sûr faire plus simple, mais ce pattern est censé pouvoir traiter bien d'autres cas).

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    Je peux même te dire que ta pattern ne matche aucune chaîne de caractères!

    Le modificateur u se place après le délimiteur de pattern et pas avant.

    De plus, ce modificateur va aussi changer le contenu de \w (tous les lettres et les chiffres UNICODE, alors qu'avant il s'en tenait à la plage ASCII). Donc si tu veux conserver ce que \w était censé contenir avant, enlève le, et écrit directement son contenu soit: A-Za-z0-9_.
    Autre solution: tu gardes le \w, tu enlèves le modificateur u et à la place tu commences la pattern (immédiatement après le délimiteur) par (*UTF)

  6. #6
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    pour la réponse.

    T'aurais pas oublier de dormir ?

    Dernier point : ma pattern doit matcher avec les caractères chinois (peut pas mettre d'exemple car DVP les connait pas)(y en a plein, c'est leurs noms et prénoms). Comment on peut faire ?

  7. #7
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    Je dors par à coups!

    La classe de caractères contenant n'importe quelle lettre quelque soit l'alphabet est : \p{L}. Mais bien que cette classe soit pratique, elle contient aussi des alphabets qui ne t'intéresseront pas comme des alphabets de langues mortes et des langues que tu ne vises peut-être pas.

    Pour les lettres chinoises, il existe la classe \p{Han}, pour l'alphabet latin, \p{Latin} (mais regarde la table UNICODE car bon nombre de lettres ne t'intéresseront pas dans la classe Latin).
    Bref toujours dans l'optique d'éviter d'avoir à taper les lettres une par une dans ta classe de caractères, n'hésite pas à utiliser des rangs si tu veux être plus précis: de même que tu peux écrire A-Z ou b-y, tu peux écrire À-Ö ou \x{00C0}-\x{00D6} en utilisant les code points, toujours avec la table sous les yeux pour voir ce que le rang contient.

  8. #8
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Ne sachant pas quels sont les codes Unicode qui m'intéressent, j'ai préféré utiliser la classe \p{han}. Mais je ne sais pas où l'écrire. $pattern = '#(?xx)\A[A-Za-z0-9_ \p{han} \- ( ) , Č Ū Ė È É Á Ñ Ó Ö É Í Ú Ć Ž Š & \/ . \h \' "]*\z #u'; donne
    Warning: preg_match(): Compilation failed: unknown property name after \P or \p at offset 26 in C:\projets\ticket_rawsrc\model\JobClass.php on line 63
    Comment faudrait-il faire ?

  9. #9
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    En n'oubliant pas la majuscule à "han" (=> "Han"). Sinon il est très bien là où il est.

  10. #10
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Merci ; c'est bon.

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

Discussions similaires

  1. oracle 10g XE n'accepte pas les accents
    Par gnaoui_9999 dans le forum Oracle
    Réponses: 6
    Dernier message: 27/08/2007, 18h47
  2. VB .NET n'accepte pas les chr(127+
    Par vincentweb dans le forum VB.NET
    Réponses: 6
    Dernier message: 17/02/2007, 20h07
  3. n'accepte pas les apostrophes
    Par flo456 dans le forum Langage
    Réponses: 6
    Dernier message: 18/09/2006, 15h14
  4. La fonction BuilCriteria n'accepte pas les points
    Par Tofalu dans le forum Access
    Réponses: 3
    Dernier message: 10/07/2006, 13h00
  5. Le '%' en SQL ne remplace pas les espaces...
    Par njac dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/09/2004, 18h10

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