php - una - strpos
¿Cómo verifico si una cadena contiene una palabra específica? (30)
Considerar:
$a = ''How are you?'';
if ($a contains ''are'')
echo ''true'';
Supongamos que tengo el código anterior, ¿cuál es la forma correcta de escribir la declaración if ($a contains ''are'')
?
Compruebe si la cadena contiene palabras específicas?
Esto significa que la cadena debe resolverse en palabras (vea la nota a continuación).
Una forma de hacer esto y especificar los separadores es 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'');
?>
Una carrera da
$ 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: Aquí no queremos decir palabra para cada secuencia de símbolos.
Una definición práctica de palabra es en el sentido del motor de expresión regular de PCRE, donde las palabras son subcadenas que consisten solo en caracteres de palabras, y están separadas por caracteres que no son palabras.
Un carácter de "palabra" es cualquier letra o dígito o el carácter de subrayado, es decir, cualquier carácter que pueda formar parte de una "palabra" de Perl. La definición de letras y dígitos está controlada por las tablas de caracteres de PCRE, y puede variar si se lleva a cabo una coincidencia específica del entorno (..)
Aquí hay una pequeña función de utilidad que es útil en situaciones como esta
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
Debe usar el formato de mayúsculas y minúsculas, por lo que si el valor ingresado es small
o caps
, no 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";
}
?>
Aquí stripos encuentra aguja en heystack sin considerar el caso (pequeño / tapas).
Debe usar operadores idénticos / no idénticos porque strpos puede devolver 0 como valor de índice. Si le gustan los operadores ternarios, considere usar lo siguiente (parece un poco al revés, lo admito):
echo FALSE === strpos($a,''are'') ? ''false'': ''true'';
En PHP, la mejor manera de verificar si una cadena contiene una determinada subcadena, es usar una función auxiliar simple como esta:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
Explicación:
- strpos() encuentra la posición de la primera aparición de una subcadena que strpos() mayúsculas y minúsculas en una cadena.
- stripos() encuentra la posición de la primera aparición de una subcadena insensible a mayúsculas en una cadena.
-
myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
asegura quemyFunction
siempre devuelve un valor booleano y corrige un comportamiento inesperado cuando el índice de la subcadena es 0. -
$caseSensitive ? A : B
$caseSensitive ? A : B
selecciona strpos() o stripos() para hacer el trabajo, dependiendo del valor de$caseSensitive
.
Salida:
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)
Estoy un poco impresionado de que ninguna de las respuestas aquí que utilizaron strpos
, strstr
y funciones similares mencionara Multibyte String Functions todavía (2015-05-08).
Básicamente, si tiene problemas para encontrar palabras con caracteres específicos de algunos idiomas , como alemán, francés, portugués, español, etc. (por ejemplo: ä , é , ô , ç , º , ñ ), es posible que desee preceder Las funciones con mb_
. Por lo tanto, la respuesta aceptada usaría mb_strpos
o mb_stripos
(para el emparejamiento insensible a mayúsculas) en su lugar:
if (mb_strpos($a,''are'') !== false) {
echo ''true'';
}
Si no puede garantizar que todos sus datos mb_
100% en UTF-8 , puede usar las funciones mb_
.
Un buen artículo para comprender por qué es The Absolute Minimum Todo desarrollador de software Absolutamente, positivamente debe saber sobre Unicode y los conjuntos de caracteres (sin excusas) por Joel Spolsky .
Hacer uso de la coincidencia entre mayúsculas y minúsculas utilizando stripos()
:
if (stripos($string,$stringToSearch) !== false) {
echo ''true'';
}
La función strpos funciona bien, pero si desea realizar case-insensitive
comprobación de case-insensitive
de una palabra en un párrafo, puede utilizar la función stripos
de PHP
.
Por ejemplo,
$result = stripos("I love PHP, I love PHP too!", "php");
if ($result === false) {
// Word does not exist
}
else {
// Word exists
}
Encuentre la posición de la primera aparición de una subcadena que no distingue entre mayúsculas y minúsculas en una cadena.
Si la palabra no existe en la cadena, devolverá falso; de lo contrario, devolverá la posición de la palabra.
La siguiente función también funciona y no depende de ninguna otra función; utiliza solo la manipulación de cadenas nativas de PHP. Personalmente, no lo recomiendo, pero puedes ver cómo 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;
}
}
Prueba:
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
La versión de mano corta.
$result = false!==strpos($a, ''are'');
No use preg_match()
si solo quiere comprobar si una cadena está contenida en otra cadena. Use strpos()
o strstr()
lugar ya que serán más rápidos. ( http://in2.php.net/preg_match )
if (strpos($text, ''string_name'') !== false){
echo ''get the string'';
}
Para determinar si una cadena contiene otra cadena, puede usar la función 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";
}
?>
PRECAUCIÓN:
Si la aguja que está buscando está al comienzo del pajar, regresará a la posición 0, si hace una ==
comparación que no funcionará, tendrá que hacer una ===
Un signo ==
es una comparación y comprueba si la variable / expresión / constante a la izquierda tiene el mismo valor que la variable / expresión / constante a la derecha.
Un signo ===
es una comparación para ver si dos variables / expresiones / constantes son iguales AND
tienen el mismo tipo, es decir, ambas son cadenas o ambas son números enteros.
Para encontrar una ''palabra'', en lugar de una serie de letras que de hecho podrían formar parte de otra palabra, lo siguiente sería una buena solución.
$string = ''How are you?'';
$array = explode(" ", $string);
if (in_array(''are'', $array) ) {
echo ''Found the word'';
}
Peer a SamGoody y Lego Stormtroopr comenta.
Si está buscando un algoritmo PHP para clasificar los resultados de búsqueda según la proximidad / relevancia de varias palabras, aquí encontrará una manera rápida y fácil de generar resultados de búsqueda solo con PHP:
Problemas con los otros métodos de búsqueda booleanos como strpos()
, preg_match()
, strstr()
o stristr()
- no puedo buscar múltiples palabras
- los resultados no están clasificados
Método PHP basado en Vector Space Model y tf-idf (término frecuencia - frecuencia de documentos inversa):
Suena difícil pero es sorprendentemente fácil.
Si queremos buscar varias palabras en una cadena, el problema principal es ¿cómo asignamos un peso a cada una de ellas?
Si pudiéramos ponderar los términos en una cadena en función de qué tan representativos son de la cadena en su conjunto, podríamos ordenar nuestros resultados por los que mejor coincidan con la consulta.
Esta es la idea del modelo de espacio vectorial, no muy lejos de cómo funciona la búsqueda de texto completo de SQL:
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;
}
CASO 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
)
CASO 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
)
CASO 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
)
Se pueden realizar muchas mejoras, pero el modelo proporciona una forma de obtener buenos resultados de las consultas naturales, que no tienen operadores booleanos como strpos()
, preg_match()
, strstr()
o stristr()
.
NOTA BENE
Opcionalmente eliminando la redundancia antes de buscar las palabras.
reduciendo así el tamaño del índice y dando como resultado menos requisitos de almacenamiento
menos E / S de disco
Indización más rápida y, por consiguiente, búsqueda más rápida.
1. normalización
- Convertir todo el texto a minúsculas
2. Eliminación de palabras clave
- Eliminar palabras del texto que no tengan un significado real (como ''y'', ''o'', ''el'', ''para'', etc.)
3. Sustitución del diccionario.
Reemplace las palabras con otras que tengan un significado idéntico o similar. (Por ejemplo, reemplace las instancias de ''hambriento'' y ''hambriento'' con ''hambre'')
Se pueden realizar otras medidas algorítmicas (bola de nieve) para reducir aún más las palabras a su significado esencial.
La sustitución de nombres de colores por sus equivalentes hexadecimales.
La reducción de los valores numéricos al reducir la precisión son otras formas de normalizar el texto.
RECURSOS
- http://linuxgazette.net/164/sephton.html
- http://snowball.tartarus.org/
- Puntuación en la búsqueda de texto completo en MySQL
- 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/
Podría usar expresiones regulares, es mejor para la coincidencia de palabras en comparación con strpos como lo mencionaron otros usuarios, también devolverá verdadero para cadenas como tarifa, cuidado, mirada fija, etc. Esto puede evitarse simplemente en la expresión regular utilizando los límites de palabras.
Un partido simple para son podría ser algo como esto:
$a = ''How are you?'';
if (preg_match(''//bare/b/'',$a))
echo ''true'';
En el lado del rendimiento, strpos es aproximadamente tres veces más rápido y ten en mente que, cuando hice un millón de comparaciones a la vez, tomó un partido preg de 1.5 segundos para terminar y para strpos tomó 0.5 segundos.
Puedes usar la función strpos()
que se usa para encontrar la aparición de una cadena dentro de otra:
$a = ''How are you?'';
if (strpos($a, ''are'') !== false) {
echo ''true'';
}
Tenga en cuenta que el uso de !== false
es deliberado; strpos()
devuelve el desplazamiento en el que comienza la cadena de la aguja en la cadena del pajar, o el false
booleano si no se encuentra la aguja. Como 0 es un desplazamiento válido y 0 es "falsey", no podemos usar construcciones más simples como !strpos($a, ''are'')
.
Puedes usar la función strstr
:
$haystack = "I know programming";
$needle = "know";
$flag = strstr($haystack, $needle);
if ($flag){
echo "true";
}
Sin usar una función 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 ";
}
Se puede hacer de tres maneras 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
}
Si bien la mayoría de estas respuestas le dirán si aparece una subcadena en su cadena, eso no suele ser lo que quiere si está buscando una palabra en particular, y no una subcadena .
¿Cual es la diferencia? Las subcadenas pueden aparecer en otras palabras:
- Los "son" al principio de "área"
- Los "son" al final de "liebre"
- Los "son" en medio de "tarifas".
Una forma de mitigar esto sería usar una expresión regular junto con los límites de las palabras ( /b
):
function containsWord($str, $word)
{
return !!preg_match(''#//b'' . preg_quote($word, ''#'') . ''//b#i'', $str);
}
Este método no tiene los mismos falsos positivos mencionados anteriormente, pero sí tiene algunos casos de borde propios. Los límites de palabras coinciden con los caracteres que no son palabras ( /W
), que van a ser cualquier cosa que no sea az
, AZ
, 0-9
o _
. Eso significa que los dígitos y los guiones bajos se contarán como caracteres de palabras y los escenarios como este fallarán:
- Los "son" en "¿Qué estás pensando?"
- El "are" in "lol u dunno wut that are4?"
Si desea algo más preciso que esto, tendrá que comenzar a analizar la sintaxis del idioma inglés, y esa es una lata de gusanos bastante grande (y, de todos modos, supone un uso adecuado de la sintaxis, lo que no siempre es cierto).
Si desea comprobar si la cadena contiene varias palabras específicas, puede hacerlo:
$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";
}
Esto es útil para evitar el spam cuando se envían correos electrónicos, por ejemplo.
Si desea evitar el problema "falsey" y "truthy", puede utilizar substr_count:
if (substr_count($a, ''are'') > 0) {
echo "at least one ''are'' is present!";
}
Es un poco más lento que los strpos pero evita los problemas de comparación.
Tal vez podrías usar algo como esto:
<?php
findWord(''Test all OK'');
function findWord($text) {
if (strstr($text, ''ok'')) {
echo ''Found a word'';
}
else
{
echo ''Did not find a word'';
}
}
?>
Tuve algunos problemas con esto, y finalmente elegí crear mi propia solución. Sin usar el motor de expresiones regulares :
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;
}
Puede notar que las soluciones anteriores no son una respuesta para la palabra que se usa como prefijo para otra. Para usar tu ejemplo:
$a = ''How are you?'';
$b = "a skirt that flares from the waist";
$c = "are";
Con los ejemplos anteriores, tanto $a
como $b
contienen $c
, pero es posible que desee que su función le diga que solo $a
contiene $c
.
Una cadena se puede verificar con la siguiente función:
function either_String_existor_not($str, $character) {
if (strpos($str, $character) !== false) {
return true;
}
return false;
}
strpos() :
<?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.";
}
?>
substr_count
respuestas que utilizan substr_count
comprueban si el resultado es >0
. Pero como la instrucción if
considera que cero es lo mismo que falso , puede evitar esa comprobación y escribir directamente:
if (substr_count($a, ''are'')) {
Para comprobar si no está presente, agregue el !
operador:
if (!substr_count($a, ''are'')) {
if (preg_match(''/(are)/'', $a)) {
echo ''true'';
}