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 :

Manipulation de chaine de caractères [RegEx]


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut Manipulation de chaine de caractères
    Bonjour à tous,

    et merci de votre aide !

    je rencontre un souci de syntaxe dans les expressions régulières...

    je suis en train de créer un moteur de recherche dans mon site,
    j'ai le champ "contenu" de ma table - $dnn['descriptif']
    et le mot ou l'expression recherchée - $rec

    je souhaite afficher uniquement la chaine de caractère contenant les 10 mots précédents ma recherche, la recherche, et les 10 mots suivants.

    j'ai cherché du coté des fonctions ereg() et eregi() mais je ne sais pas bien comment rédiger ma syntaxe avec les tutos que j'ai trouvé.
    après quelques essais infructueux, j'ai ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $chaine=eregi($rec,$dnn['descriptif'],$reg);
    echo $reg[0];
    qui n'affiche que le mot recherché.

    comment m'y prendre ?

    En vous remerciant de votre aide...

  2. #2
    Membre Expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Par défaut
    Ne jamais sous-estimer les tableaux php :

    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
    <?php
     
    function search($wordSearch, $text, $nbWords = 10) {
     
        //On enlève la ponctuation pour la recherche
        $carToReplace = array('.', ',', '?', '!', ':', ';', '"', '...', '(', ')', "'");
     
        $textToSearch = str_replace($carToReplace, "", $text);
     
        $tabTextToSearch = explode(" ", $textToSearch);
        $tabText = explode(" ", $text);
     
        $resSearch = array_search($wordSearch, $tabTextToSearch);
        if ($resSearch === false) {
            return false;
        }
     
        $indexFirstWord = $resSearch - $nbWords;
        if ($indexFirstWord < 0) {
            $indexFirstWord = 0;
        }
     
        $before = array_slice($tabText, $indexFirstWord, $nbWords);
        $after = array_slice($tabText, $resSearch + 1, $nbWords);
     
        return array(
            'before' => implode(' ', $before),
            'word' => $wordSearch,
            'after' => implode(' ', $after),
        );
    }
     
    $text = "Voici un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les '10 mots' qui se situe avant "
            . "et après ce mot, pour voir comment c'est facile d'utiliser les tableaux en php.";
     
    $wordSearch = "particulier";
     
    $resSearch = search($wordSearch, $text);
     
    if ($resSearch !== false) {
        print_r($resSearch);
    } else {
        echo "Mot non trouvé dans la chaîne";
    }
    Cette fonction est adaptable en fonction de ce que tu souhaites faire exactement (actuellement c'est une recherche la plus stricte possible qui est applquée).

    Une remarque au passage, les fonction de type "ereg" sont dépréciées depuis Php 5.3, privilégier l'utilisation des fonction "preg_..." à la place.

  3. #3
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut Merci !!
    merci Spartacusply

    Cette fonction est intéressante, je m'y suis appuyée.
    j'ai fait une modification pour rendre l'affichage plus agréable.
    au lieu d'avoir les array et [0] etc. ça s'affiche simplement, avec le mot en gras. voici le code modifié :
    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
    <?php
     
    function search($wordSearch, $text, $nbWords = 10) {
     
        //On enlève la ponctuation pour la recherche
        $carToReplace = array('.', ',', '?', '!', ':', ';', '"', '...', '(', ')', "'");
     
        $textToSearch = str_replace($carToReplace, "", $text);
     
        $tabTextToSearch = explode(" ", $textToSearch);
        $tabText = explode(" ", $text);
     
        $resSearch = array_search($wordSearch, $tabTextToSearch);
        if ($resSearch === false) {
            return false;
        }
     
        $indexFirstWord = $resSearch - $nbWords;
        if ($indexFirstWord < 0) {
            $indexFirstWord = 0;
        }
     
        $before = array_slice($tabText, $indexFirstWord, $nbWords);
        $after = array_slice($tabText, $resSearch + 1, $nbWords);
     
        return array(
            implode(' ', $before),
            '<strong>'.$wordSearch.'</strong>',
            implode(' ', $after),
        );
    }
     
    $text = "Voici un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les '10 mots' qui se situe avant et après ce mot, pour voir comment c'est facile d'utiliser les tableaux en php.";
     
    $wordSearch = "mot";
     
    $resSearch = search($wordSearch, $text);
     
    if ($resSearch !== false) {
        echo implode(" ",$resSearch);
    } else {
        echo "Mot non trouvé dans la chaîne";
    }
    ?>
    le résultat de ce test est :
    un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les

    j'ai par contre remarqué un souci qui est aussi présent dans ta version, et qui me semble un peut gênant :
    lorsqu'il y a moins de 10 mots avant le mot recherché, il affiche 10 mots (dont le mot recherché), puis il affiche la suite, dont une partie est donc en doublon.
    exemple :
    avec le mot "lequel" en recherche, j'ai ceci :
    "Voici un texte de texte, dans lequel on va chercher lequel on va chercher un mot en particulier et qui affichera"
    doublon de "lequel on va chercher"


    je vais essayer d'améliorer ça, et je reviens.
    de même je vais protéger les accents.

    à plus tard !

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    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 : 3 018
    Par défaut
    Déjà il faut définir ce qu'est un mot. Pour l'exemple, je choisi qu'un mot est un ensemble de caractère composé uniquement de chiffres et de lettres, et délimité par des caractères n'étant pas un chiffre ou une lettre, ou par les limites de la chaîne.

    Donc il faut trouver une classe de caractère qui correspond à cette définition. La classe \p{Xan} contient les chiffres et lettres de tous les alphabets contenus dans les tables unicode. \P{Xan} correspond à son contraire.

    Pour résoudre le problème des limites de la chaîne (il n'y a pas forcément 10 mots entre le début de la chaîne et l'expression recherchée), il suffit d'utiliser {0,10} comme quantificateur, en prenant soin de le rendre non-gourmand {0,10}? pour qu'il s'arrête avant l'expression recherchée et qu'il ne l'englobe pas.

    On aboutit alors au pattern:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (?:\p{Xan}+\P{Xan}+){0,10}?expression(?:\P{Xan}+\p{Xan}+){0,10}
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getExcerpt($needle, $str) {
        $pattern = '~((?:\p{Xan}+\P{Xan}+){0,10}?)(' . preg_quote($needle, '~') . ')((?:\P{Xan}+\p{Xan}+){0,10})~i';    
        if (preg_match($pattern, $str, $match)) 
            return $match[1] . '<strong>' . $match[2] . '</strong>' . $match[3];
        else
            return false;
    }
    Tu peux aussi te limiter aux lettres en utilisant \p{L} et \P{L}.

  5. #5
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut

    Je suis un peu perdue du coup...

    je comprend ta démarche, mais je suis moins à l'aise avec ton code...

    alors comment mixer la première fonction avec la tienne ?
    dois-je mettre les deux fonctions les unes sous les autres ? mais quelles sont les variables que je fais passer ?

    j'ai fait un test :
    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
    function search($wordSearch, $text, $nbWords = 10) {
     
        //On enlève la ponctuation pour la recherche
        $carToReplace = array('.', ',', '?', '!', ':', ';', '"', '...', '(', ')', "'");
     
        $textToSearch = str_replace($carToReplace, "", $text);
     
        $tabTextToSearch = explode(" ", $textToSearch);
        $tabText = explode(" ", $text);
     
        $resSearch = array_search($wordSearch, $tabTextToSearch);
        if ($resSearch === false) {
            return false;
        }
     
        $indexFirstWord = $resSearch - $nbWords;
        if ($indexFirstWord < 0) {
            $indexFirstWord = 0;
        }
     
        $before = array_slice($tabText, $indexFirstWord, $nbWords);
        $after = array_slice($tabText, $resSearch + 1, $nbWords);
     
        return array(
            implode(' ', $before),
            '<strong>'.$wordSearch.'</strong>',
            implode(' ', $after),
        );
    }
     
    $text = "Voici un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les '10 mots' qui se situe avant et après ce mot, pour voir comment c'est facile d'utiliser les tableaux en php.";
     
    $wordSearch = "après";
     
    $resSearch = search($wordSearch, $text);
     
    if ($resSearch !== false) {
        echo implode(" ",$resSearch);
    } else {
        echo "Mot non trouvé dans la chaîne";
    }
    ////////
     
     function getExcerpt($needle, $str) {
        $pattern = '~((?:\p{Xan}+\P{Xan}+){0,10}?)(' . preg_quote($needle, '~') . ')((?:\P{Xan}+\p{Xan}+){0,10})~i';    
        if (preg_match($pattern, $str, $match)) 
            return $match[1] . '<strong>' . $match[2] . '</strong>' . $match[3];
        else
            return false;
    }
    getExcerpt($texte,$wordSearch);
    et j'obtiens :
    Warning: preg_match() [function.preg-match]: Compilation failed: unknown property name after \P or \p at offset 10 in /web/.....test-chaine2.php on line 48

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    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 : 3 018
    Par défaut
    En fait non, les deux approches sont différentes. Celle que je présente utilise les expressions régulières , l'autre utilise les manipulations de tableaux. Je te conseille d'utiliser l'approche avec laquelle tu te sens le plus à l'aise dans un premier temps, quitte à revenir à l'autre ensuite.

    Voici un exemple d'utilisation. J'ai modifier la fonction pour que le nombre de mots soit pris en compte:
    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
    $text = "Voici un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les '10 mots' qui se situe avant et après ce mot, pour voir comment c'est facile d'utiliser les tableaux en php.";
     
    $wordSearch = "après";
     
    function getExcerpt($needle, $str, $limit = 10) {
        $pattern = '~((?:\p{Xan}+\P{Xan}+){0,' . $limit .'}?)(' . preg_quote($needle, '~')
                 . ')((?:\P{Xan}+\p{Xan}+){0,' . $limit . '})~iu';    
        if (preg_match($pattern, $str, $match)) 
            return $match[1] . '<strong>' . $match[2] . '</strong>' . $match[3];
        else
            return false;
    }
     
    var_dump (getExcerpt($wordSearch, $text, 5));
    var_dump (getExcerpt($wordSearch, $text));
    var_dump (getExcerpt('choucroute', $text, 8));
    Il est possible si tu utilises une version de PHP pas trop récente que \p{Xan} ne soit pas encore disponible (d'où le warning). Dans ce cas tu peux modifier le pattern:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $pattern = '~((?:[\p{L}\p{N}]+[^\p{L}\p{N}]+){0,' . $limit .'}?)(' . preg_quote($needle, '~')
             . ')((?:[^\p{L}\p{N}]+[\p{L}\p{N}]+){0,' . $limit . '})~iu';
    Ce qui revient au même (\p{L} pour les lettres, \p{N} pour les chiffres, [\p{L}\p{N}] => un chiffre ou une lettre)

  7. #7
    Membre Expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Par défaut
    j'ai par contre remarqué un souci qui est aussi présent dans ta version, et qui me semble un peut gênant :
    lorsqu'il y a moins de 10 mots avant le mot recherché, il affiche 10 mots (dont le mot recherché), puis il affiche la suite, dont une partie est donc en doublon.
    exemple :
    avec le mot "lequel" en recherche, j'ai ceci :
    "Voici un texte de texte, dans lequel on va chercher lequel on va chercher un mot en particulier et qui affichera"
    doublon de "lequel on va chercher"
    Ah oui en effet il y a quelque chose à changer, on ne vas plus afficher 10 mots s'il n'y a pas 10 mots avant.

    Voici la fonction modifiée (à partir la ligne 18) :

    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
    <?php
     
    function search($wordSearch, $text, $nbWords = 10) {
     
        //On enlève la ponctuation pour la recherche
        $carToReplace = array('.', ',', '?', '!', ':', ';', '"', '...', '(', ')', "'");
     
        $textToSearch = str_replace($carToReplace, "", $text);
     
        $tabTextToSearch = explode(" ", $textToSearch);
        $tabText = explode(" ", $text);
     
        $resSearch = array_search($wordSearch, $tabTextToSearch);
        if ($resSearch === false) {
            return false;
        }
     
        $nbWordsBefore = $nbWords;
        $indexFirstWord = $resSearch - $nbWords;
        if ($indexFirstWord < 0) {
            $nbWordsBefore = $nbWords + $indexFirstWord;
            $indexFirstWord = 0;
        }
     
        $before = array_slice($tabText, $indexFirstWord, $nbWordsBefore);
        $after = array_slice($tabText, $resSearch + 1, $nbWords);
     
        return array(
            'before' => implode(' ', $before),
            'word' => $wordSearch,
            'after' => implode(' ', $after),
        );
    }
     
    $text = "Voici un texte de texte, dans lequel on va chercher un mot en particulier et qui affichera (ceci est un test) les '10 mots' qui se situe avant "
            . "et après ce mot, pour voir comment c'est facile d'utiliser les tableaux en php.";
     
    $wordSearch = "lequel";
     
    $resSearch = search($wordSearch, $text);
     
    if ($resSearch !== false) {
        print_r($resSearch);
    } else {
        echo "Mot non trouvé dans la chaîne";
    }
    Concernant les 2 méthodes proposées, personnellement je préfère privilégier la manipulation de tableau dès que je le peut car je trouve ça compréhensible et plus lisible. Après la solution des expressions régulières, proposée par CosmoKnacki, est très bien aussi mais je m'y sens personnellement beaucoup moins à l'aise. Je doit aussi avouer que sur des très longs textes (plusieurs millers de mots), cette méthode est sans doute plus performante.

    Et une dernière chose, tu peux simplifier le retour de ta fonction pour afficher une phrase directement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return implode(' ', $before) . '<strong>' . $wordSearch . '</strong>' . implode(' ', $after);

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

Discussions similaires

  1. Comment manipuler une chaine de caractère
    Par belmehdi17 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 11/03/2008, 16h03
  2. Manipulation de chaine de caractères, supression d'une apostrophe
    Par pmithrandir dans le forum Scripts/Batch
    Réponses: 6
    Dernier message: 28/11/2007, 07h55
  3. Manipulation des chaines de caractères en c
    Par developppez dans le forum C
    Réponses: 8
    Dernier message: 29/04/2007, 13h04
  4. Réponses: 4
    Dernier message: 14/10/2006, 23h38
  5. Réponses: 4
    Dernier message: 20/08/2004, 10h59

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