Comment vérifier si une chaîne contient un mot spécifique?

2661

Considérer:

$a = 'How are you?';

if ($a contains 'are')
    echo 'true';

Supposons que j'ai le code ci-dessus, quelle est la bonne façon d'écrire l'instruction if ($a contains 'are')?

Charles Yeung
la source

Réponses:

6895

Vous pouvez utiliser la strpos()fonction utilisée pour rechercher l'occurrence d'une chaîne à l'intérieur d'une autre:

$a = 'How are you?';

if (strpos($a, 'are') !== false) {
    echo 'true';
}

Notez que l'utilisation de !== falseest délibérée ( != falseni === truene retournera le résultat souhaité); strpos()renvoie soit l'offset auquel la chaîne d'aiguille commence dans la chaîne de botte de foin, soit le booléen falsesi l'aiguille n'est pas trouvée. Puisque 0 est un décalage valide et 0 est "falsey", nous ne pouvons pas utiliser des constructions plus simples comme !strpos($a, 'are').

codaddict
la source
261
Très tard pour la fête, mais faites attention à cela. Cela retournera également vrai pour la chaîne "Vous vous souciez?"
DTest
167
@DTest - bien oui, bien sûr, il retournera vrai parce que la chaîne contient «are». Si vous recherchez spécifiquement le mot ARE, vous devrez effectuer plus de vérifications comme, par exemple, vérifier s'il y a un caractère ou un espace avant le A et après le E.
jsherk
40
Très bons commentaires ci-dessus! Je n'utilise jamais! = Ou ==, après tout! == et === est la meilleure option (à mon avis) tous les aspects considérés (vitesse, précision, etc.).
Melsi
10
@jsherk Pourquoi pas des regex, alors? Quelque chose comme "sont".
Giulio Muscarello
22
J'ai tendance à éviter ce problème en utilisant toujours strpos($a, 'are') > -1pour tester true. Du point de vue du débogage, je trouve que mon cerveau gaspille moins de cycles d'horloge pour déterminer si la ligne est écrite correctement quand je n'ai pas à compter les signes égaux contigus.
equazcion
608

Vous pouvez utiliser des expressions régulières, c'est mieux pour la correspondance de mots strposque comme mentionné par d'autres utilisateurs, cela retournera également vrai pour les chaînes telles que le tarif, le soin, le regard, etc. Cela peut simplement être évité dans l'expression régulière en utilisant des limites de mots.

Une simple correspondance pour are pourrait ressembler à ceci:

$a = 'How are you?';

if (preg_match('/\bare\b/', $a)) {
    echo 'true';
}

Du côté des performances, strposc'est environ trois fois plus rapide et j'ai en tête, quand j'ai fait un million de comparaisons à la fois, il a fallu preg_match1,5 seconde pour terminer et pour strposcela a pris 0,5 seconde.

Edit: afin de rechercher n'importe quelle partie de la chaîne, pas seulement mot par mot, je recommanderais d'utiliser une expression régulière comme

$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
    echo 'true';
}

À ila fin de l'expression régulière, l'expression régulière est insensible à la casse, si vous ne le souhaitez pas, vous pouvez la laisser de côté.

Maintenant, cela peut être assez problématique dans certains cas car la chaîne de recherche $ n'est pas nettoyée de quelque façon que ce soit, je veux dire, elle peut ne pas passer la vérification dans certains cas comme s'il s'agissait d' $searchune entrée utilisateur, ils peuvent ajouter une chaîne qui pourrait se comporter comme une expression régulière différente ...

En outre, voici un excellent outil pour tester et voir les explications de diverses expressions régulières Regex101

Pour combiner les deux ensembles de fonctionnalités en une seule fonction polyvalente (y compris avec une sensibilité à la casse sélectionnable), vous pouvez utiliser quelque chose comme ceci:

function FindString($needle,$haystack,$i,$word)
{   // $i should be "" or "i" for case insensitive
    if (strtoupper($word)=="W")
    {   // if $word is "W" then word search instead of string in string search.
        if (preg_match("/\b{$needle}\b/{$i}", $haystack)) 
        {
            return true;
        }
    }
    else
    {
        if(preg_match("/{$needle}/{$i}", $haystack)) 
        {
            return true;
        }
    }
    return false;
    // Put quotes around true and false above to return them as strings instead of as bools/ints.
}
Breezer
la source
9
@ Alexander.Plutov deuxième de tout ce que vous me donnez -1 et pas la question? cmon il faut 2 secondes pour google la réponse google.com/…
Breezer
64
+1 C'est une façon horrible de rechercher une chaîne simple, mais de nombreux visiteurs de SO recherchent un moyen de rechercher l'une de leurs propres sous-chaînes, et il est utile que la suggestion ait été évoquée. Même le PO pourrait avoir trop simplifié - faites-lui connaître ses alternatives.
SamGoody
72
Techniquement, la question demande comment trouver des mots et non une sous-chaîne. Cela m'a vraiment aidé car je peux l'utiliser avec des limites de mots regex. Les alternatives sont toujours utiles.
15
+1 pour la réponse et -1 au commentaire @ plutov.by car, strpos n'est qu'une seule vérification, tandis que regexp vous pouvez vérifier plusieurs mots en même temps ex: preg_match (/ are | you | not /)
albanx
4
Les expressions régulières devraient être la méthode de dernier recours. Leur utilisation dans des tâches triviales doit être découragée. J'insiste là-dessus depuis la hauteur de nombreuses années de fouille de mauvais code.
yentsun
257

Voici une petite fonction utilitaire qui est utile dans des situations comme celle-ci

// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
    return strpos($haystack, $needle) !== false;
}
ejunker
la source
74
@RobinvanBaalen En fait, cela peut améliorer la lisibilité du code. De même, les downvotes sont censés être pour les (très) mauvaises réponses, pas pour les «neutres».
Xaqq
37
Les fonctions @RobinvanBaalen sont presque par définition pour la lisibilité (pour communiquer l'idée de ce que vous faites). Comparez ce qui est plus lisible: if ($email->contains("@") && $email->endsWith(".com)) { ...ouif (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
Brandin
3
@RobinvanBaalen dans les règles de fin est censé être brisé. Sinon, les gens ne trouveraient pas de nouvelles façons inventives de faire les choses :). De plus, je dois admettre que j'ai du mal à comprendre les choses comme sur martinfowler.com. Supposez que la bonne chose à faire est d'essayer vous-même les choses et de découvrir quelles approches sont les plus pratiques.
James P.
5
Un autre avis: avoir une fonction utilitaire que vous pouvez facilement envelopper peut aider au débogage. De plus, il pousse le cri pour de bons optimiseurs qui éliminent ces frais généraux dans les services de production. Donc, toutes les opinions ont des points valables. ;)
Tino
18
Bien sûr, cela est utile. Vous devriez encourager cela. Que se passe-t-il si en PHP 100 il existe un moyen nouveau et plus rapide de trouver des emplacements de chaîne? Voulez-vous changer tous vos endroits où vous appelez strpos? Ou souhaitez-vous modifier uniquement le contenu de la fonction ??
Cosmin
143

Bien que la plupart de ces réponses vous diront si une sous-chaîne apparaît dans votre chaîne, ce n'est généralement pas ce que vous voulez si vous recherchez un mot particulier , et non une sous - chaîne .

Quelle est la différence? Les sous-chaînes peuvent apparaître entre d'autres mots:

  • Les "sont" au début de la "zone"
  • Les "sont" à la fin du "lièvre"
  • Les "sont" au milieu des "tarifs"

Une façon d'atténuer cela serait d'utiliser une expression régulière couplée à des limites de mots ( \b):

function containsWord($str, $word)
{
    return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}

Cette méthode n'a pas les mêmes faux positifs mentionnés ci-dessus, mais elle a ses propres cas limites. Limites correspondent mot sur les caractères non-mot ( \W), qui vont être quelque chose qui n'est pas a-z, A-Z, 0-9ou _. Cela signifie que les chiffres et les traits de soulignement seront comptés comme des caractères de mot et que des scénarios comme celui-ci échoueront:

  • Le "êtes" dans "Que pensez-vous _?"
  • Le "sont" dans "lol u dunno wut ceux are4?"

Si vous voulez quelque chose de plus précis que cela, vous devrez commencer à analyser la syntaxe en anglais, et c'est une très grosse boîte de vers (et suppose une utilisation correcte de la syntaxe, de toute façon, ce qui n'est pas toujours une donnée).

FtDRbwLXw6
la source
24
ce devrait être la réponse canonique. Parce que nous recherchons des mots et non des sous - chaînes , l'expression régulière est appropriée. J'ajouterai également qui \bcorrespond à deux choses qui \Wne le font pas, ce qui le rend idéal pour trouver des mots dans une chaîne: il correspond au début de la chaîne ( ^) et à la fin de la chaîne ( $)
code_monk
cela devrait être la bonne réponse .. le reste des réponses trouvera "sont" dans une chaîne comme "vous vous souciez" .. Comme mentionné par @Dtest
Robert Sinclair
@RobertSinclair Est-ce si mauvais? Si vous me demandiez si la chaîne «vous souciez-vous» contient-elle le mot «sont», je dirais «oui». Le mot "are" est clairement une sous-chaîne de cette chaîne. C'est une question distincte de "" "Est" sont "l'un des mots de la chaîne" vous vous souciez "" "".
Paul
@Paulpro Eventhough OP n'a pas précisé que $ a est une phrase, je suis presque sûr qu'elle était implicite. Sa question était donc de savoir comment détecter le mot à l'intérieur de la phrase. Pas si un mot contient un mot à l'intérieur de celui-ci, ce qui, je suppose, ne serait pas pertinent plus souvent qu'autrement.
Robert Sinclair
@Jimbo ça fonctionne, il vous manque juste le `\` 3v4l.org/ZRpYi
MetalWeirdo
125

Pour déterminer si une chaîne contient une autre chaîne, vous pouvez utiliser la fonction PHP strpos () .

int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

<?php

$haystack = 'how are you';
$needle = 'are';

if (strpos($haystack,$needle) !== false) {
    echo "$haystack contains $needle";
}

?>

MISE EN GARDE:

Si l'aiguille que vous recherchez se trouve au début de la botte de foin, elle retournera en position 0, si vous faites une ==comparaison qui ne fonctionnera pas, vous devrez faire un===

Un ==signe est une comparaison et teste si la variable / expression / constante à gauche a la même valeur que la variable / expression / constante à droite.

Un ===signe est une comparaison pour voir si deux variables / expressions / constantes sont égales ANDont le même type - c'est-à-dire que les deux sont des chaînes ou les deux sont des entiers.

Jose Vega
la source
67

Regardezstrpos() :

<?php
    $mystring = 'abc';
    $findme   = 'a';
    $pos = strpos($mystring, $findme);

    // Note our use of ===. Simply, == would not work as expected
    // because the position of 'a' was the 0th (first) character.
    if ($pos === false) {
        echo "The string '$findme' was not found in the string '$mystring'.";
    }
    else {
        echo "The string '$findme' was found in the string '$mystring',";
        echo " and exists at position $pos.";
    }
?>
Haim Evgi
la source
62

Utiliser strstr()ou stristr()si votre recherche doit être insensible à la casse serait une autre option.

glutorange
la source
9
Remarque sur la page php.net/manual/en/function.strstr.php : Remarque: Si vous souhaitez uniquement déterminer si une aiguille particulière se produit dans la botte de foin, utilisez plutôt la fonction strpos () plus rapide et moins gourmande en mémoire.
Jo Smo
@tastro Existe-t-il des références fiables à ce sujet?
Wayne Whitty
Cela pourrait être plus lent, mais à mon humble avis strstr($a, 'are')est beaucoup plus élégant que le laid strpos($a, 'are') !== false. PHP a vraiment besoin d'une str_contains()fonction.
Paul Spiegel
Cela me souffle que ce n'est pas la réponse acceptée
kurdtpage
45

Utilisez la correspondance insensible à la casse en utilisant stripos():

if (stripos($string,$stringToSearch) !== false) {
    echo 'true';
}
Shankar Damodaran
la source
45

Regardez les commentaires de SamGoody et Lego Stormtroopr.

Si vous recherchez un algorithme PHP pour classer les résultats de recherche en fonction de la proximité / pertinence de plusieurs mots, voici un moyen rapide et facile de générer des résultats de recherche avec PHP uniquement:

Problèmes avec les autres méthodes de recherche booléenne tels que strpos(), preg_match(), strstr()oustristr()

  1. impossible de rechercher plusieurs mots
  2. les résultats ne sont pas classés

Méthode PHP basée sur le modèle d'espace vectoriel et tf-idf (terme fréquence – fréquence du document inverse):

Cela semble difficile mais étonnamment facile.

Si nous voulons rechercher plusieurs mots dans une chaîne, le problème principal est de savoir comment attribuer un poids à chacun d'eux?

Si nous pouvions pondérer les termes dans une chaîne en fonction de leur représentativité de la chaîne dans son ensemble, nous pourrions classer nos résultats par ceux qui correspondent le mieux à la requête.

C'est l'idée du modèle d'espace vectoriel, non loin du fonctionnement de la recherche SQL en texte intégral:

function get_corpus_index($corpus = array(), $separator=' ') {

    $dictionary = array();

    $doc_count = array();

    foreach($corpus as $doc_id => $doc) {

        $terms = explode($separator, $doc);

        $doc_count[$doc_id] = count($terms);

        // tf–idf, short for term frequency–inverse document frequency, 
        // according to wikipedia is a numerical statistic that is intended to reflect 
        // how important a word is to a document in a corpus

        foreach($terms as $term) {

            if(!isset($dictionary[$term])) {

                $dictionary[$term] = array('document_frequency' => 0, 'postings' => array());
            }
            if(!isset($dictionary[$term]['postings'][$doc_id])) {

                $dictionary[$term]['document_frequency']++;

                $dictionary[$term]['postings'][$doc_id] = array('term_frequency' => 0);
            }

            $dictionary[$term]['postings'][$doc_id]['term_frequency']++;
        }

        //from http://phpir.com/simple-search-the-vector-space-model/

    }

    return array('doc_count' => $doc_count, 'dictionary' => $dictionary);
}

function get_similar_documents($query='', $corpus=array(), $separator=' '){

    $similar_documents=array();

    if($query!=''&&!empty($corpus)){

        $words=explode($separator,$query);

        $corpus=get_corpus_index($corpus, $separator);

        $doc_count=count($corpus['doc_count']);

        foreach($words as $word) {

            if(isset($corpus['dictionary'][$word])){

                $entry = $corpus['dictionary'][$word];


                foreach($entry['postings'] as $doc_id => $posting) {

                    //get term frequency–inverse document frequency
                    $score=$posting['term_frequency'] * log($doc_count + 1 / $entry['document_frequency'] + 1, 2);

                    if(isset($similar_documents[$doc_id])){

                        $similar_documents[$doc_id]+=$score;

                    }
                    else{

                        $similar_documents[$doc_id]=$score;

                    }
                }
            }
        }

        // length normalise
        foreach($similar_documents as $doc_id => $score) {

            $similar_documents[$doc_id] = $score/$corpus['doc_count'][$doc_id];

        }

        // sort from  high to low

        arsort($similar_documents);

    }   

    return $similar_documents;
}

CAS 1

$query = 'are';

$corpus = array(
    1 => 'How are you?',
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RÉSULTAT

Array
(
    [1] => 0.52832083357372
)

CAS 2

$query = 'are';

$corpus = array(
    1 => 'how are you today?',
    2 => 'how do you do',
    3 => 'here you are! how are you? Are we done yet?'
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RÉSULTATS

Array
(
    [1] => 0.54248125036058
    [3] => 0.21699250014423
)

CAS 3

$query = 'we are done';

$corpus = array(
    1 => 'how are you today?',
    2 => 'how do you do',
    3 => 'here you are! how are you? Are we done yet?'
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RÉSULTATS

Array
(
    [3] => 0.6813781191217
    [1] => 0.54248125036058
)

Il y a beaucoup d'améliorations à apporter , mais le modèle offre un moyen d'obtenir de bons résultats des requêtes naturelles, qui ne sont pas des opérateurs booléens tels que strpos(), preg_match(), strstr()ou stristr().

NOTA BENE

Éliminer éventuellement la redondance avant de rechercher les mots

  • réduisant ainsi la taille de l'index et entraînant moins de stockage

  • moins d'E / S disque

  • indexation plus rapide et recherche par conséquent plus rapide.

1. Normalisation

  • Convertir tout le texte en minuscules

2. Élimination des mots vides

  • Éliminez les mots du texte qui n'ont pas de sens réel (comme 'et', 'ou', 'le', 'pour', etc.)

3. Substitution de dictionnaire

  • Remplacez les mots par d'autres qui ont une signification identique ou similaire. (ex: remplacer les cas de «faim» et «faim» par «faim»)

  • D'autres mesures algorithmiques (boule de neige) peuvent être effectuées pour réduire davantage les mots à leur signification essentielle.

  • Le remplacement des noms de couleurs par leurs équivalents hexadécimaux

  • La réduction des valeurs numériques en réduisant la précision sont d'autres moyens de normaliser le texte.

RESSOURCES

RafaSashi
la source
40

Si vous voulez éviter le problème "falsey" et "truey", vous pouvez utiliser substr_count:

if (substr_count($a, 'are') > 0) {
    echo "at least one 'are' is present!";
}

C'est un peu plus lent que strpos mais ça évite les problèmes de comparaison.

Alan Piralla
la source
Il revient falsepour "êtes-vous sûr?" puisque le poste strposest0
Hafenkranich
30

Une autre option consiste à utiliser la fonction strstr () . Quelque chose comme:

if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}

Point à noter: la fonction strstr () est sensible à la casse. Pour une recherche non sensible à la casse, utilisez la fonction stristr () .

YashG99
la source
1
strstr () renvoie FALSE si l'aiguille n'a pas été trouvée. Un strlen n'est donc pas nécessaire.
Ayesh K
29
if (preg_match('/(are)/', $a)) {
   echo 'true';
}
joan16v
la source
3
Je reçois l'avertissement suivant:WARNING preg_match(): Delimiter must not be alphanumeric or backslash
Pathros
27

Je suis un peu impressionné qu'aucune des réponses ici qui a utilisé strpos, strstret des fonctions similaires mentionné Fonctions Multibyte Chaîne encore (08/05/2015).

Fondamentalement, si vous rencontrez des difficultés pour trouver des mots avec des caractères spécifiques à certaines langues , tels que l'allemand, le français, le portugais, l'espagnol, etc. (par exemple: ä , é , ô , ç , º , ñ ), vous voudrez peut-être précéder les fonctions avec mb_. Par conséquent, la réponse acceptée utiliserait mb_strposou mb_stripos(pour une correspondance insensible à la casse) à la place:

if (mb_strpos($a,'are') !== false) {
    echo 'true';
}

Si vous ne pouvez pas garantir que toutes vos données sont à 100% en UTF-8 , vous pouvez utiliser les mb_fonctions.

Un bon article pour comprendre pourquoi est le minimum absolu que tout développeur de logiciels doit absolument, positivement, connaître sur l'Unicode et les jeux de caractères (sans excuses!) Par Joel Spolsky .

Armfoot
la source
25

En PHP, la meilleure façon de vérifier si une chaîne contient une certaine sous-chaîne, est d'utiliser une simple fonction d'aide comme celle-ci:

function contains($haystack, $needle, $caseSensitive = false) {
    return $caseSensitive ?
            (strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
            (stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}

Explication:

  • strpos recherche la position de la première occurrence d'une sous-chaîne sensible à la casse dans une chaîne.
  • stripos recherche la position de la première occurrence d'une sous-chaîne insensible à la casse dans une chaîne.
  • myFunction($haystack, $needle) === FALSE ? FALSE : TRUEgarantit que myFunctionrenvoie toujours un booléen et corrige un comportement inattendu lorsque l'index de la sous-chaîne est 0.
  • $caseSensitive ? A : Bsélectionne soit strposou stripospour effectuer le travail, selon la valeur de $caseSensitive.

Production:

var_dump(contains('bare','are'));            // Outputs: bool(true)
var_dump(contains('stare', 'are'));          // Outputs: bool(true)
var_dump(contains('stare', 'Are'));          // Outputs: bool(true)
var_dump(contains('stare', 'Are', true));    // Outputs: bool(false)
var_dump(contains('hair', 'are'));           // Outputs: bool(false)
var_dump(contains('aren\'t', 'are'));        // Outputs: bool(true)
var_dump(contains('Aren\'t', 'are'));        // Outputs: bool(true)
var_dump(contains('Aren\'t', 'are', true));  // Outputs: bool(false)
var_dump(contains('aren\'t', 'Are'));        // Outputs: bool(true)
var_dump(contains('aren\'t', 'Are', true));  // Outputs: bool(false)
var_dump(contains('broad', 'are'));          // Outputs: bool(false)
var_dump(contains('border', 'are'));         // Outputs: bool(false)
John Slegers
la source
22

La fonction ci-dessous fonctionne également et ne dépend d'aucune autre fonction; il utilise uniquement la manipulation de chaînes PHP native. Personnellement, je ne recommande pas cela, mais vous pouvez voir comment cela fonctionne:

<?php

if (!function_exists('is_str_contain')) {
  function is_str_contain($string, $keyword)
  {
    if (empty($string) || empty($keyword)) return false;
    $keyword_first_char = $keyword[0];
    $keyword_length = strlen($keyword);
    $string_length = strlen($string);

    // case 1
    if ($string_length < $keyword_length) return false;

    // case 2
    if ($string_length == $keyword_length) {
      if ($string == $keyword) return true;
      else return false;
    }

    // case 3
    if ($keyword_length == 1) {
      for ($i = 0; $i < $string_length; $i++) {

        // Check if keyword's first char == string's first char
        if ($keyword_first_char == $string[$i]) {
          return true;
        }
      }
    }

    // case 4
    if ($keyword_length > 1) {
      for ($i = 0; $i < $string_length; $i++) {
        /*
        the remaining part of the string is equal or greater than the keyword
        */
        if (($string_length + 1 - $i) >= $keyword_length) {

          // Check if keyword's first char == string's first char
          if ($keyword_first_char == $string[$i]) {
            $match = 1;
            for ($j = 1; $j < $keyword_length; $j++) {
              if (($i + $j < $string_length) && $keyword[$j] == $string[$i + $j]) {
                $match++;
              }
              else {
                return false;
              }
            }

            if ($match == $keyword_length) {
              return true;
            }

            // end if first match found
          }

          // end if remaining part
        }
        else {
          return false;
        }

        // end for loop
      }

      // end case4
    }

    return false;
  }
}

Tester:

var_dump(is_str_contain("test", "t")); //true
var_dump(is_str_contain("test", "")); //false
var_dump(is_str_contain("test", "test")); //true
var_dump(is_str_contain("test", "testa")); //flase
var_dump(is_str_contain("a----z", "a")); //true
var_dump(is_str_contain("a----z", "z")); //true 
var_dump(is_str_contain("mystringss", "strings")); //true 
Jason OOO
la source
13
Pourriez-vous s'il vous plaît me dire pourquoi dans le monde vous utiliseriez une fonction comme celle-ci, alors que strpos est une solution parfaitement viable? ...
sg3s
3
@ sg3s: vous avez tout à fait raison, cependant, strpos également basé sur quelque chose comme ça, aussi, je ne l'ai pas posté pour le représentant juste pour partager un peu de connaissances
Jason OOO
dernier var_dump est faux
Sunny
1
@Sunny: c'était une faute de frappe: var_dump (is_str_contain ("mystringss", "strings")); // true
Jason OOO
22

Vous pouvez utiliser la strstrfonction:

$haystack = "I know programming";
$needle   = "know";
$flag = strstr($haystack, $needle);

if ($flag){

    echo "true";
}

Sans utiliser de fonction intégrée:

$haystack  = "hello world";
$needle = "llo";

$i = $j = 0;

while (isset($needle[$i])) {
    while (isset($haystack[$j]) && ($needle[$i] != $haystack[$j])) {
        $j++;
        $i = 0;
    }
    if (!isset($haystack[$j])) {
        break;
    }
    $i++;
    $j++;

}
if (!isset($needle[$i])) {
    echo "YES";
}
else{
    echo "NO ";
}
Arshid KV
la source
2
Se bloque si vous recherchez le premier mot.
T30
20

J'ai eu quelques problèmes avec cela et j'ai finalement choisi de créer ma propre solution. Sans utiliser le moteur d' expression régulière :

function contains($text, $word)
{
    $found = false;
    $spaceArray = explode(' ', $text);

    $nonBreakingSpaceArray = explode(chr(160), $text);

    if (in_array($word, $spaceArray) ||
        in_array($word, $nonBreakingSpaceArray)
       ) {

        $found = true;
    }
    return $found;
 }

Vous pouvez remarquer que les solutions précédentes ne sont pas une réponse pour le mot utilisé comme préfixe pour un autre. Pour utiliser votre exemple:

$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";

Avec les exemples ci-dessus, les deux $aet $bcontient $c, mais vous voudrez peut-être que votre fonction vous dise que $acontient uniquement $c.

Decebal
la source
1
vous vouliez probablement dire: $found = falseau début
ralentissement
1
votre fonction peut ne pas fonctionner si le mot est lié par une virgule, un point d'interrogation ou un point. par exemple "ce que vous voyez est ce que vous obtenez." et vous voulez déterminer si "get" est dans la phrase. Notez l'arrêt complet à côté de "get". Dans ce cas, votre fonction retourne false. il est recommandé d'utiliser l'expression régulière ou substr (je pense qu'il utilise de toute façon l'expression régulière) pour rechercher / remplacer les chaînes.
Lightbringer
@lightbringer vous ne pourriez pas vous tromper davantage avec votre recommandation, qu'est-ce que cela signifie pour vous "c'est recommandé"? il n'y a pas de personne suprême qui recommande ou approuve. Il s'agit de l'utilisation du moteur d'expression régulière en php qui est un trou noir dans la langue elle-même, vous voudrez peut-être essayer de mettre une correspondance regex dans une boucle et de comparer les résultats.
Decebal
Cette réponse est mal démontrée et échoue avec de nombreux scénarios étendus. Je ne vois aucun avantage à utiliser cette technique. Voici la fonction personnalisée raffinée et l'appel itéré: 3v4l.org/E9dfD Je n'ai aucun intérêt à éditer ce wiki parce que je trouve que c'est une perte de temps pour les chercheurs.
mickmackusa
18

Une autre option pour rechercher l'occurrence d'un mot dans une chaîne à l'aide de strstr () et stristr () est la suivante:

<?php
    $a = 'How are you?';
    if (strstr($a,'are'))  // Case sensitive
        echo 'true';
    if (stristr($a,'are'))  // Case insensitive
        echo 'true';
?>
Sadikhasan
la source
C'est à l'envers. Le ien stristrsignifie insensible.
Adam Merrifield
18

Beaucoup de réponses qui utilisent des substr_countcontrôles si le résultat est >0. Mais comme l' ifinstruction considère zéro comme étant faux , vous pouvez éviter cette vérification et écrire directement:

if (substr_count($a, 'are')) {

Pour vérifier s'il n'est pas présent, ajoutez l' !opérateur:

if (!substr_count($a, 'are')) {
T30
la source
Eh bien ... partiellement vrai, en php 0 == false est vrai, mais 0 === false est faux
Andrejs Gubars
17

Cela peut se faire de trois manières différentes:

 $a = 'How are you?';

1- stristr ()

 if (strlen(stristr($a,"are"))>0) {
    echo "true"; // are Found
 } 

2- strpos ()

 if (strpos($a, "are") !== false) {
   echo "true"; // are Found
 }

3- preg_match ()

 if( preg_match("are",$a) === 1) {
   echo "true"; // are Found
 }
Shashank Singh
la source
bien, mais preg_match est risqué car il peut retourner faux ou 0. Vous devriez tester === 1 dans # 3
Shapeshifter
14

La version courte

$result = false!==strpos($a, 'are');
Somwang Souksavatd
la source
5
Bien que cet extrait de code puisse résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Bono
14

Afin de trouver un «mot», plutôt que l'occurrence d'une série de lettres qui pourraient en fait faire partie d'un autre mot, ce qui suit serait une bonne solution.

$string = 'How are you?';
$array = explode(" ", $string);

if (in_array('are', $array) ) {
    echo 'Found the word';
}
DJC
la source
5
il échouera si $stringc'estAre are, are?
Sunny
13

Vous devez utiliser un format insensible à la casse, donc si la valeur entrée est smallou si capscela n'a pas d'importance.

<?php
$grass = "This is pratik joshi";
$needle = "pratik";
if (stripos($grass,$needle) !== false) { 

 /*If i EXCLUDE : !== false then if string is found at 0th location, 
   still it will say STRING NOT FOUND as it will return '0' and it      
   will goto else and will say NOT Found though it is found at 0th location.*/
    echo 'Contains word';
}else{
    echo "does NOT contain word";
}
?>

Ici, stripos trouve une aiguille dans une meule de foin sans considérer le cas (petit / casquettes).

Échantillon PHPCode avec sortie

Pratik
la source
13

Vous pourriez peut-être utiliser quelque chose comme ceci:

<?php
    findWord('Test all OK');

    function findWord($text) {
        if (strstr($text, 'ok')) {
            echo 'Found a word';
        }
        else
        {
            echo 'Did not find a word';
        }
    }
?>
Mathias Stavrou
la source
12

Ne pas utiliser preg_match()si vous souhaitez uniquement vérifier si une chaîne est contenue dans une autre chaîne. Utilisez strpos()ou à la strstr()place car ils seront plus rapides. ( http://in2.php.net/preg_match )

if (strpos($text, 'string_name') !== false){
   echo 'get the string';
}
Vinod Joshi
la source
12

Si vous voulez vérifier si la chaîne contient plusieurs mots spécifiques, vous pouvez faire:

$badWords = array("dette", "capitale", "rembourser", "ivoire", "mandat");

$string = "a string with the word ivoire";

$matchFound = preg_match_all("/\b(" . implode($badWords,"|") . ")\b/i", $string, $matches);

if ($matchFound) {
    echo "a bad word has been found";
}
else {
    echo "your string is okay";
}

C'est utile pour éviter le spam lors de l'envoi d'emails par exemple.

Julien
la source
10

La fonction strpos fonctionne bien, mais si vous voulez case-insensitivevérifier un mot dans un paragraphe, vous pouvez utiliser la striposfonction de PHP.

Par exemple,

$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
    // Word does not exist
}
else {
    // Word exists
}

Trouvez la position de la première occurrence d'une sous-chaîne insensible à la casse dans une chaîne.

Si le mot n'existe pas dans la chaîne, il retournera false sinon il renverra la position du mot.

Akshay Khale
la source
9

Vous devez utiliser des opérateurs identiques / non identiques car strpos peut renvoyer 0 comme valeur d'index. Si vous aimez les opérateurs ternaires, pensez à utiliser ce qui suit (semble un peu en arrière, je l'admets):

echo FALSE === strpos($a,'are') ? 'false': 'true';
Shapeshifter
la source
8

Vérifiez si la chaîne contient des mots spécifiques?

Cela signifie que la chaîne doit être résolue en mots (voir la note ci-dessous).

Une façon de le faire et de spécifier les séparateurs utilise preg_split( doc ):

<?php

function contains_word($str, $word) {
  // split string into words
  // separators are substrings of at least one non-word character
  $arr = preg_split('/\W+/', $str, NULL, PREG_SPLIT_NO_EMPTY);

  // now the words can be examined each
  foreach ($arr as $value) {
    if ($value === $word) {
      return true;
    }
  }
  return false;
}

function test($str, $word) {
  if (contains_word($str, $word)) {
    echo "string '" . $str . "' contains word '" . $word . "'\n";
  } else {
    echo "string '" . $str . "' does not contain word '" . $word . "'\n" ;
  }
}

$a = 'How are you?';

test($a, 'are');
test($a, 'ar');
test($a, 'hare');

?>

Une course donne

$ php -f test.php                   
string 'How are you?' contains word 'are' 
string 'How are you?' does not contain word 'ar'
string 'How are you?' does not contain word 'hare'

Remarque: Ici, nous ne voulons pas dire mot pour chaque séquence de symboles.

Une définition pratique du mot est en ce sens que le moteur d'expression régulière PCRE, où les mots sont des sous-chaînes constituées uniquement de caractères de mot, étant séparés par des caractères non-mot.

Un caractère "mot" est une lettre ou un chiffre ou le caractère de soulignement, c'est-à-dire tout caractère pouvant faire partie d'un "mot" Perl. La définition des lettres et des chiffres est contrôlée par les tables de caractères de PCRE et peut varier si une correspondance spécifique aux paramètres régionaux a lieu (..)

mvw
la source
7

Une autre solution pour une chaîne spécifique:

$subject = 'How are you?';
$pattern = '/are/';
preg_match($pattern, $subject, $match);
if ($match[0] == 'are') {
    echo true;
}

Vous pouvez également utiliser la strpos()fonction.

devpro
la source