Como posso verificar se um texto contém uma palavra específica?
considere:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
suponha que eu tenho o código acima, qual é a maneira correta de escrever a declaração if ($a contains 'are')
?
30 answers
Podes usar o strpos()
função que é usada para encontrar a ocorrência de uma cadeia dentro de outra:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
Lembre-se que a utilização de !== false
é deliberada; strpos()
devolve a posição em que a corda da agulha começa na corda do Palheiro, ou o booleano false
se a agulha não for encontrada. Uma vez que 0 é um offset válido e 0 é "falsey", não podemos usar construções mais simples como !strpos($a, 'are')
.
Você poderia usar expressões regulares, é melhor para correspondência de Palavras em comparação com strpos como mencionado por outros usuários que também retornará verdadeiro para strings, tais como tarifa, cuidado, olhar, etc. Isto pode simplesmente ser evitado na expressão regular usando limites de palavras.
Um jogo simples para are pode ser parecido com isto:
$a = 'How are you?';
if (preg_match('/\bare\b/',$a))
echo 'true';
Do lado da performance, o strpos é três vezes mais rápido e tem em mente que, quando fiz um milhão de comparações ao mesmo tempo, foi preciso um jogo de prég de 1,5. segundos para terminar e para strpos levou 0,5 segundos.
Aqui está uma pequena função útil que é útil em situações como esta
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
Embora a maioria destas respostas lhe digam se uma substring aparece na sua string, normalmente não é o que quer se está à procura de uma palavra em particular , e não de uma substring .
Qual é a diferença? Substratos podem aparecer em outras palavras:- O " são "no início da"área"
- O " são "no fim da"lebre" Os "estão" no meio das "tarifas"
\b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
Este método não tem os mesmos falsos positivos assinalados acima, mas tem alguns casos extremos próprios. Os limites das palavras coincidem com os caracteres não-Palavra (\W
), que vão ser qualquer coisa que não sejaa-z
, A-Z
, 0-9
, ou _
. Isso significa que os dígitos e os sublinhados serão contados como caracteres de palavra e cenários como este falharão:
- O " são " em " O que _ are_ você a pensar?"
- O "são" em "lol u don't wut those are4?"
Se você quiser algo mais preciso do que isso, você terá que começar a fazer o processamento de sintaxe em língua inglesa, e isso é uma grande lata de worms (e assume o uso adequado da sintaxe, de qualquer maneira, o que nem sempre é um dado).
Para determinar se uma cadeia contém outra cadeia de caracteres, poderá usar a função 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";
}
?>
Atenção:
Se a agulha que procura estiver no início do Palheiro, irá devolver a posição 0, Se fizer uma comparação ==
que não irá funcionar, terá de fazer uma ===
Um sinal ==
é uma comparação e testes se a variável / expressão / constante à esquerda tem o mesmo valor que o valor variável / expressão / constante à direita.
A ===
sign é uma comparação para ver se duas variáveis / expresões / constantes são iguais AND
têm o mesmo tipo - ou seja, ambos são cadeias ou ambos são inteiros.
<?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.";
}
?>
Faça uso de case-insensitve matching Usando stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo 'true';
}
Se quiser evitar o problema" falsey "e" truthy", pode usar o subconjunto:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
É um pouco mais lento que o strpos, mas evita os problemas de comparação.
Se está à procura de um algoritmo de PHP para os resultados de pesquisa de classificação com base na proximidade / relevância de várias palavras aqui vem uma maneira rápida e fácil de gerar resultados de pesquisa apenas com PHP:
Problemas com os outros métodos de busca booleanos, como strpos()
, preg_match()
, strstr()
ou stristr()
- não se pode procurar por várias palavras
- os resultados não têm fundamento
PHP método baseado em Vector Space Model e tf-idf (term frequency-inverse document frequency):
Parece difícil, mas é surpreendentemente fácil. Se queremos procurar por várias palavras numa cadeia, o problema principal é como atribuímos um peso a cada uma delas?Se pudéssemos pesar os Termos numa string baseada no quão representativos eles são da string como um todo, podemos encomendar os nossos resultados por aqueles que melhor correspondem à consulta.
Esta é a ideia do modelo de espaço vetorial, não muito longe de como a pesquisa de texto completo SQL funciona:
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;
}
Processo 1
$query = 'are';
$corpus = array(
1 => 'How are you?',
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
RESULTADO
Array
(
[1] => 0.52832083357372
)
Processo 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>';
Resultados
Array
(
[1] => 0.54248125036058
[3] => 0.21699250014423
)
Processo 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>';
Resultados
Array
(
[3] => 0.6813781191217
[1] => 0.54248125036058
)
Há muitas melhorias a fazer.
mas o modelo oferece uma maneira de obter bons resultados de consultas naturais,
que não existem operadores booleanos como strpos()
, preg_match()
, strstr()
ou stristr()
.
NOTA BENE
opcionalmente eliminar a redundância antes de procurar as palavras
Reduzindo assim a dimensão do índice e reduzindo as necessidades de armazenamento
Menos disco I / O
Indexação mais rápida e, consequentemente, uma busca mais rápida.
1. Normalização
- converter todo o texto para baixo processo
2. Eliminação da palavra-chave
- eliminar palavras do texto que não têm significado real (como 'e',' ou',' o',' para', etc.)
3. Substituição do dicionário
Substituir palavras por outras que tenham um significado idêntico ou semelhante. (ex:substituir os casos de "fome" e "fome" por "fome"')
Outras medidas algorítmicas (bola de neve) podem ser realizadas para reduzir ainda mais palavras para o seu significado essencial.
Substituição dos nomes de cores pelos seus equivalentes hexadecimais
A redução dos valores numéricos pela redução da precisão são outras formas de normalizar o texto.
Recursos
- http://linuxgazette.net/164/sephton.html
- http://snowball.tartarus.org/
- Pontuação De Pesquisa De Texto Completo Do MySQL Explicado
- http://dev.mysql.com/doc/internals/en/full-text-search.html
- http://en.wikipedia.org/wiki/Vector_space_model
- http://en.wikipedia.org/wiki/Tf%E2%80%93idf
- http://phpir.com/simple-search-the-vector-space-model/
strpos
, strstr
e funções similares mencionadas funções de cadeia de múltiplos ainda (2015-05-08).
Basicamente, se você está tendo dificuldade em encontrar palavras com caracteres específicos para algumas línguas , Como Alemão, Francês, Português, Espanhol, etc. (exemplo: ä, é, ô, ç, º, ñ), poderá preceder as funções com mb_
. Por conseguinte, a resposta aceite utilizaria mb_strpos
ou mb_stripos
(para a correspondência sem distinção de maiúsculas) em vez disso:
if (mb_strpos($a,'are') !== false) {
echo 'true';
}
Se não puder garantir isso todos os seus dados são 100% em UTF-8, pode querer usar as funções mb_
.
A função abaixo também funciona e não depende de nenhuma outra função; ela usa apenas manipulação de cadeia de Php nativa. Pessoalmente, eu não recomendo isso, mas você pode ver como funciona:
<?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;
}
}
Teste:
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
if (preg_match('are', $a)) {
echo 'true';
}
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;
}
Você pode notar que as soluções anteriores não são uma resposta para a palavra sendo usada como um prefixo para outra. Para usar o seu exemplo:
$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";
Com as amostras acima, $a
e $b
contêm $c
, mas pode querer que a sua função lhe diga que apenas $a
contém $c
.
Pode usar a função strstr
:
$haystack = "I know programming";
$needle = "know";
$flag = strstr($haystack, $needle);
if ($flag){
echo "true";
}
Sem usar uma função incorporada:
$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 ";
}
Em PHP, a melhor maneira de verificar se uma cadeia contém uma determinada substring, é usar uma função auxiliar simples como esta:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
Explicação:
-
strpos
Encontra a posição da primeira ocorrência de uma sub-sequência sensível a maiúsculas numa cadeia de caracteres. -
stripos
Encontra a posição da primeira ocorrência de um sub-texto sem distinção de maiúsculas numa cadeia de caracteres. -
myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
assegura quemyFunction
devolve sempre um booleano e corrige o inesperado comportamento quando o índice da sub-estrutura é 0. -
$caseSensitive ? A : B
selecionastrpos
oustripos
para fazer o trabalho, dependendo do valor de$caseSensitive
.
Resultado:
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)
A versão em mão curta
$result = false!==strpos($a, 'are');
A fim de encontrar uma 'palavra', ao invés da ocorrência de uma série de letras que poderiam de fato ser uma parte de outra palavra, o seguinte seria uma boa solução.
$string = 'How are you?';
$array = explode(" ", $string);
if (in_array('are', $array) ) {
echo 'Found the word';
}
Deverá usar um formato insensível à capitalização, por isso, se o valor indicado estiver em small
ou caps
, não importa.
<?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";
}
?>
Aqui as listras encontram a agulha na seringa Sem considerando o caso (pequenas/tampas).
Amostra de código PHP com saída
Pode ser feito de três maneiras diferentes:
$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
}
Muitas respostas que usam substr_count
verifica se o resultado é >0
. Mas uma vez que a declaração if
considera zero o igual a falso , Você pode evitar essa verificação e escrever diretamente:
if (substr_count($a, 'are')) {
Para verificar se não está presente, adicione o !
operador:
if (!substr_count($a, 'are')) {
<?php
findWord('Test all OK');
function findWord($text) {
if (strstr($text, 'ok')) {
echo 'Found a word';
}
else
{
echo 'Did not find a word';
}
}
?>
Não utilize preg_match()
se só quiser verificar se um texto está contido noutro texto. Utilize strpos()
ou strstr()
em vez disso, pois serão mais rápidos. ([6]} http://in2.php.net/preg_match)
if (strpos($text, 'string_name') !== false){
echo 'get the string';
}
Você precisa usar operadores idênticos / não idênticos porque strpos pode retornar 0 como o seu valor de índice. Se você gosta de operadores ternários, considere usar o seguinte (parece um pouco para trás eu admito):
echo FALSE === strpos($a,'are') ? 'false': 'true';
Se quiser verificar se o texto contém várias palavras específicas, pode fazer:
$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";
}
Isto é útil para evitar spam ao enviar e-mails, por exemplo.
A função strpos funciona bem, mas se você quiser fazer case-insensitive
a verificação de uma palavra num parágrafo então você pode fazer uso da função stripos
de PHP
.
Por exemplo,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Encontre a posição da primeira ocorrência de um sub-texto insensível a maiúsculas numa cadeia de caracteres.
Se a palavra não existe na cadeia então ela retornará falsa caso contrário retornará a posição da palavra.
Verificar se o texto contém palavras específicas?
Isto significa que o texto tem de ser resolvido em palavras (Ver nota abaixo).
Uma maneira de fazer isto e especificar os separadores está a usar 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');
?>
Uma corrida dá
$ 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'
Nota: aqui não queremos dizer palavra para cada sequência de símbolos.
Uma definição prática de palavra é no sentido do motor de expressão regular PCRE, onde as palavras são substratos que consistem em apenas caracteres de palavra, sendo separados por caracteres não-Palavra.
Um carácter de "palavra" é qualquer letra ou dígito ou o carácter sublinhado, ou seja, qualquer personagem que possa ser parte de uma "palavra" Perl. O a definição de letras e dígitos é controlada pelo carácter do PCRE tables, and may vary if locale-specific matching is taking place (..)
Um texto pode ser verificado com a função abaixo:
function either_String_existor_not($str, $character) {
if (strpos($str, $character) !== false) {
return true;
}
return false;
}