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 :

Regex preg_replace pour hashtag


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Juin 2018
    Messages : 4
    Par défaut Regex preg_replace pour hashtag
    Bonjour,
    Ça fait plusieurs semaines que je bloque sur une fonction regex. Je cherche à transformer un hashtag de type "#RoyaumeUni" en "Royaume Uni", c'est à dire insérer un espace dans un hashtag à chaque majuscule précédée d'une minuscule mais uniquement pour les mots commençant par #
    Et il faudrait que le pattern fonctionne aussi avec #CoréeDuSud par exemple.
    Actuellement j'utilise preg_replace("/(?:\B#)?(([ÁÉÍÓÚÝÂÊÎÔÛÄËÏÖÀÈÌÒÙāŠšŽÅŒÆÇÑßÕA-Z]+[áéíóúýâêîôûäëïöàèìòùœæñßðāğa-z0-9_]+|\d+(?=\1*$)))/u", " $1", $text); mais déjà il prend en compte les mots sans le # et l'espace avant le $1 ajoute aussi un espace supplémentaire avant le hashtag.
    Merci

  2. #2
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Une astuce pour les lettres accentuées : tu peux utiliser les caractères unicodes plutôt que lister toutes les lettres :
    [ÁÉÍÓÚÝÂÊÎÔÛÄËÏÖÀÈÌÒÙāŠšŽÅŒÆÇÑßÕA-Z] peut être remplacé par \p{Lu} et [áéíóúýâêîôûäëïöàèìòùœæñßðāğa-z] par \p{Ll}.
    Propriétés des caractères Unicode

    Sinon pour la regex proprement dite, désolée c'est au-delà de mes compétences.
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  3. #3
    Membre Expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 59
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Billets dans le blog
    8
    Par défaut
    Merci du tuyau Célira ! Je ne connaissais pas.
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  4. #4
    Candidat au Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Juin 2018
    Messages : 4
    Par défaut
    Citation Envoyé par Celira Voir le message
    Une astuce pour les lettres accentuées : tu peux utiliser les caractères unicodes plutôt que lister toutes les lettres :
    [ÁÉÍÓÚÝÂÊÎÔÛÄËÏÖÀÈÌÒÙāŠšŽÅŒÆÇÑßÕA-Z] peut être remplacé par \p{Lu} et [áéíóúýâêîôûäëïöàèìòùœæñßðāğa-z] par \p{Ll}.
    Merci Celira
    On y voit en effet plus clair, mais je n'arrive toujours pas à trouver le bon pattern lol

  5. #5
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    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 986
    Par défaut
    Une solution consiste à utiliser l'ancre \G qui matche la position de la chaîne juste après la dernière occurrence trouvée (au début de la recherche cette ancre matche aussi le début de la chaîne d'où le (?!\A) pour éliminer ce cas de figure).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $str = preg_replace('~(?:\G(?!\A)|#)(\p{Lu}\p{Ll}*+)(?=\pL)~u', '$1 ', $str);
    1) Le moteur de regex parcourt la chaîne jusqu'à ce que la seconde branche # réussisse. On capture alors la première partie (\p{Lu}\p{Ll}*+) que si celle-ci est suivie d'une lettre (?=\pL) (c'est un raccourci pour (?=\p{L})).
    2) Une première occurrence ayant été trouvée, la première branche avec l'ancre \G va donc réussir à la position suivante dans la chaîne (au niveau du "D" dans "#CoréeDuNord"), puis on capture la partie suivante.
    3) On recommence 2), jusqu'à ce que la pattern échoue (ce sera au niveau du lookahead (?=\pL)), alors on repart de 1).

    Le modificateur u indique que la chaîne et la pattern sont en utf-8 et doivent être lues comme telles et non pas octet par octet.

  6. #6
    Candidat au Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Juin 2018
    Messages : 4
    Par défaut
    Génial ! Merci CosmoKnacki !
    J'avais déjà vu cette histoire d'ancrage mais les explications n'étaient pas très claires. Cependant je teste depuis tout à l'heure, il ne fonctionne pas sur tout ce que je souhaite. C'est mon explication du début qui n'était pas assez précise, méa culpa. Je souhaite aussi que ça fonctionne sur les hashtags d'un mot, prenant en compte aussi les possibles ponctuations.
    Exemple :
    Je souhaite voyager à #NewYork aux #ÉtatsUnis, puis faire un tour au #NewEnglandConservatory à #Boston.
    devient
    Je souhaite voyager à New York aux États Unis, puis faire un tour au New England Conservatory à Boston.
    Je continue de chercher avec le pattern de CosmoKnacki

  7. #7
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    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 986
    Par défaut
    En fait le problème ne vient pas de la ponctuation, mais des hashtags ne comportant qu'un seul mot (cas auquel je n'avais pas pensé). Comme il faut obligatoirement enlever le # et qu'il n'est pas possible de faire un remplacement sans ajouter d'espace, on peut oublier preg_replace.

    Donc mieux vaut utiliser preg_replace_callback pour isoler le tag et le traiter dans un deuxième temps:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $str = preg_replace_callback('~#(\pL+)~u', function ($m) { return preg_replace('~\B(?=\p{Lu})~u', ' ', $m[1]); }, $str);
    Je viens de me rendre compte que \B avec le modificateur u ne fonctionne pas correctement avec PHP 7.3.0 alpha1 sur 3v4l.org. Donc au pire on peut écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $str = preg_replace_callback('~#(\pL+)~u', function ($m) { return preg_replace('~(*UCP)\B(?=\p{Lu})~u', ' ', $m[1]); }, $str);

Discussions similaires

  1. [RegEx] preg_replace pour désactivation de lien
    Par olbouss dans le forum Langage
    Réponses: 7
    Dernier message: 12/06/2008, 20h51
  2. [RegEx] problème sur la fonction preg_replace pour formatage
    Par medkyl dans le forum Langage
    Réponses: 4
    Dernier message: 06/02/2008, 17h37
  3. [RegEx] Pattern preg_replace pour ajouter des strong's
    Par juJuv51 dans le forum Langage
    Réponses: 1
    Dernier message: 14/11/2007, 16h00
  4. [regex] pattern pour une methode publique
    Par Invité dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 17/04/2007, 12h57
  5. Réponses: 12
    Dernier message: 04/09/2006, 17h59

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