¿Cómo compruebo si una cadena contiene una palabra específica?
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')
?
Ahora con PHP 8 puedes hacer esto usando str_contains :
if (str_contains('How are you', 'are')) {
echo 'true';
}
Tenga en cuenta : la str_contains
función siempre devolverá verdadero si $needle (la subcadena a buscar en su cadena) está vacía.
$haystack = 'Hello';
$needle = '';
if (str_contains($haystack, $needle)) {
echo "This returned true!";
}
Primero debes asegurarte de que $needle (tu subcadena) no esté vacía.
$haystack = 'How are you?';
$needle = '';
if ($needle !== '' && str_contains($haystack, $needle)) {
echo "This returned true!";
} else {
echo "This returned false!";
}
Producción :This returned false!
También vale la pena señalar que la nueva str_contains
función distingue entre mayúsculas y minúsculas.
$haystack = 'How are you?';
$needle = 'how';
if ($needle !== '' && str_contains($haystack, $needle)) {
echo "This returned true!";
} else {
echo "This returned false!";
}
Producción :This returned false!
RFC
Antes de PHP 8
Puede utilizar la strpos()
función que se utiliza para encontrar la aparición de una cadena dentro de otra:
$haystack = 'How are you?';
$needle = 'are';
if (strpos($haystack, $needle) !== false) {
echo 'true';
}
Tenga en cuenta que el uso de !== false
es deliberado (ni != false
devolverá === true
el resultado deseado); strpos()
Devuelve el desplazamiento en el que comienza la cadena de agujas en la cadena del pajar o el valor booleano false
si no se encuentra la aguja. Dado que 0 es un desplazamiento válido y 0 es "falso", no podemos usar construcciones más simples como !strpos($a, 'are')
.
Puede utilizar expresiones regulares, ya que es mejor para la coincidencia de palabras en comparación con strpos
, como lo mencionaron otros usuarios. Una strpos
verificación de are
también devolverá verdadero para cadenas como: tarifa, atención, mirada, etc. Estas coincidencias no deseadas se pueden evitar simplemente en expresiones regulares usando límites de palabras.
Una coincidencia simple are
podría verse así:
$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
En cuanto al rendimiento, strpos
es aproximadamente tres veces más rápido. Cuando hice un millón de comparaciones a la vez, me tomó preg_match
1,5 segundos terminar y strpos
0,5 segundos.
Editar: para buscar cualquier parte de la cadena, no solo palabra por palabra, recomendaría usar una expresión regular como
$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
Al i
final de la expresión regular, la expresión regular cambia para que no distinga entre mayúsculas y minúsculas; si no lo desea, puede omitirlo.
Ahora, esto puede ser bastante problemático en algunos casos ya que la cadena $search no está desinfectada de ninguna manera, quiero decir, es posible que no pase la verificación en algunos casos, ya que si $search
fuera una entrada del usuario, pueden agregar alguna cadena que podría comportarse como alguna expresión regular diferente...
Además, aquí hay una gran herramienta para probar y ver explicaciones de varias expresiones regulares Regex101.
Para combinar ambos conjuntos de funcionalidades en una única función multipropósito (incluso con distinción entre mayúsculas y minúsculas seleccionables), puede usar algo como esto:
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.
}
Una cosa más a tener en cuenta es que \b
no funcionará en otros idiomas además del inglés.
La explicación de esto y la solución se obtienen de aquí :
\b
representa el principio o el final de una palabra (límite de palabra). Esta expresión regular coincidiría con la manzana en una tarta de manzana, pero no coincidiría con la manzana en piña, carritos de manzanas o manzanas horneadas.¿Qué tal “café”? ¿Cómo podemos extraer la palabra “café” en expresiones regulares? En realidad, \bcafé\b no funcionaría. ¿Por qué? Porque “café” contiene caracteres no ASCII: é. \b no se puede usar simplemente con Unicode como समुद्र, 감사, месяц y 😉.
Cuando desee extraer caracteres Unicode, debe definir directamente caracteres que representen límites de palabras.
La respuesta:
(?<=[\s,.:;"']|^)UNICODE_WORD(?=[\s,.:;"']|$)
Entonces, para usar la respuesta en PHP, puedes usar esta función:
function contains($str, array $arr) {
// Works in Hebrew and any other unicode characters
// Thanks https://medium.com/@shiba1014/regex-word-boundaries-with-unicode-207794f6e7ed
// Thanks https://www.phpliveregex.com/
if (preg_match('/(?<=[\s,.:;"\']|^)' . $word . '(?=[\s,.:;"\']|$)/', $str)) return true;
}
Y si desea buscar una variedad de palabras, puede usar esto:
function arrayContainsWord($str, array $arr)
{
foreach ($arr as $word) {
// Works in Hebrew and any other unicode characters
// Thanks https://medium.com/@shiba1014/regex-word-boundaries-with-unicode-207794f6e7ed
// Thanks https://www.phpliveregex.com/
if (preg_match('/(?<=[\s,.:;"\']|^)' . $word . '(?=[\s,.:;"\']|$)/', $str)) return true;
}
return false;
}
A partir de PHP 8.0.0 ahora puedes usar str_contains
<?php
if (str_contains('abc', '')) {
echo "Checking the existence of the empty string will always"
return true;
}