如何检查字符串是否包含特定单词?

考虑:

$a = 'How are you?';
if ($a contains 'are')echo 'true';

假设我有上面的代码,写语句if ($a contains 'are')的正确方法是什么?

6359575 次浏览

您可以使用正则表达式,因为与strpos相比,它更适合单词匹配,正如其他用户所提到的那样。arestrpos检查也将返回true,用于字符串,例如:票价,护理,凝视等。这些意外的匹配可以通过使用单词边界在正则表达式中简单地避免。

are的简单匹配可能看起来像这样:

$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {echo 'true';}

在性能方面,strpos大约快三倍。当我一次进行100万次比较时,#1需要1.5秒才能完成,而strpos需要0.5秒。

编辑:为了搜索字符串的任何部分,而不仅仅是逐字搜索,我建议使用像

这样的正则表达式
$a = 'How are you?';$search = 'are y';if(preg_match("/{$search}/i", $a)) {echo 'true';}

正则表达式末尾的i将正则表达式更改为不区分大小写,如果您不希望这样,可以将其省略。

现在,在某些情况下,这可能是相当有问题的,因为$search字符串没有以任何方式进行消毒,我的意思是,它可能无法通过检查在某些情况下,如果$search是用户输入他们可以添加一些可能表现得像一些不同的正则表达式的字符串……

此外,这是一个测试和查看各种正则表达式解释的好工具Regex101

要将这两套功能组合成一个多用途函数(包括可选择的区分大小写),您可以使用以下内容:

function FindString($needle,$haystack,$i,$word){   // $i should be "" or "i" for case insensitiveif (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.}

还有一件事要记住,\b在英语以外的其他语言中不起作用。

对此的解释和解决方案是从这里采取的

\b表示单词的开头或结尾(单词边界)。这Regex会匹配苹果派中的苹果,但不会匹配苹果派中的苹果菠萝,苹果车或烤苹果。

“咖啡”怎么样?我们如何在正则表达式中提取“咖啡”这个词?实际上,\bcafé\b不起作用。为什么?因为"café"包含非ASCII字符:é.\b不能简单地与Unicode一起使用,例如समुद्र, 감사, месяц 😉

当您想提取Unicode字符时,应直接定义表示单词边界的字符。

答案:(?<=[\s,.:;"']|^)UNICODE_WORD(?=[\s,.:;"']|$)

所以为了在PHP中使用答案,你可以使用这个函数:

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;}

如果你想搜索单词数组,你可以使用这个:

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;}

从PHP 8.0.0开始,您现在可以使用str_contains

<?phpif (str_contains('abc', '')) {echo "Checking the existence of the empty string will always"return true;}

现在使用PHP 8,您可以使用str_contains:

if (str_contains('How are you', 'are')) {echo 'true';}

RFC

在PHP 8之前

您可以使用#0函数,该函数用于查找一个字符串在另一个字符串中的出现:

$haystack = 'How are you?';$needle   = 'are';
if (strpos($haystack, $needle) !== false) {echo 'true';}

请注意,!== false的使用是故意的(!= false=== true都不会返回所需的结果);strpos()返回针形字符串在haystack字符串中开始的偏移量,如果找不到针形,则返回布尔值false。由于0是有效偏移量,0是“false sey”,我们不能使用像!strpos($a, 'are')这样的简单结构。

看看#0

<?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.";}?>

要确定一个字符串是否包含另一个字符串,您可以使用PHP函数#0

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";}
?>

注意:

如果你正在寻找的针是在干草堆的开始,它将返回位置0,如果你做一个==比较,这将不起作用,你将需要做一个===

==符号是一个比较,测试左侧的变量/表达式/常量是否与右侧的变量/表达式/常量具有相同的值。

===符号是比较两个变量/表达式/常量是否相等AND具有相同的类型-即两者都是字符串或两者都是整数。

如果您的搜索不区分大小写,则使用#0#1是另一种选择。

这是一个在这种情况下很有用的实用函数

// returns true if $needle is a substring of $haystackfunction contains($needle, $haystack){return strpos($haystack, $needle) !== false;}

另一种选择是使用strstr()函数。类似于:

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

注意:strstr()函数区分大小写。对于不区分大小写的搜索,请使用stristr()函数。

如果你想避免“假”和“真”的问题,你可以使用substr_count:

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

它比strpos慢一点,但它避免了比较问题。

下面的函数也可以工作,不依赖于任何其他函数;它只使用原生PHP字符串操作。就个人而言,我不推荐这样做,但您可以看到它是如何工作的:

<?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 1if ($string_length < $keyword_length) return false;
// case 2if ($string_length == $keyword_length) {if ($string == $keyword) return true;else return false;}
// case 3if ($keyword_length == 1) {for ($i = 0; $i < $string_length; $i++) {
// Check if keyword's first char == string's first charif ($keyword_first_char == $string[$i]) {return true;}}}
// case 4if ($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 charif ($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;}}

测试:

var_dump(is_str_contain("test", "t")); //truevar_dump(is_str_contain("test", "")); //falsevar_dump(is_str_contain("test", "test")); //truevar_dump(is_str_contain("test", "testa")); //flasevar_dump(is_str_contain("a----z", "a")); //truevar_dump(is_str_contain("a----z", "z")); //truevar_dump(is_str_contain("mystringss", "strings")); //true
if (preg_match('/(are)/', $a)) {echo 'true';}

使用大小写无关匹配使用#0

if (stripos($string,$stringToSearch) !== false) {echo 'true';}

使用strstr()stristr()从字符串中查找单词出现的另一个选项如下所示:

<?php$a = 'How are you?';if (strstr($a,'are'))  // Case sensitiveecho 'true';if (stristr($a,'are'))  // Case insensitiveecho '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;}

您可能会注意到,前面的解决方案并不是对用作另一个词前缀的单词的答案。为了使用您的示例:

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

对于上面的示例,$a$b都包含$c,但您可能希望您的函数告诉您只有$a包含$c

如果您只想检查一个字符串是否包含在另一个字符串中,请不要使用preg_match()。请使用strpos()strstr(),因为它们会更快。(http://in2.php.net/preg_match

if (strpos($text, 'string_name') !== false){echo 'get the string';}

虽然这些答案中的大多数会告诉您子字符串是否出现在您的字符串中,但如果您正在寻找特定的而不是子串,这通常不是您想要的。

有什么区别?子字符串可以出现在其他单词中:

  • “区域”开头的“是”
  • "are"在"hare"的末尾
  • 在“票价”中间的“是”

缓解这种情况的一种方法是使用与字边界\b)耦合的正则表达式:

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

此方法没有上面提到的误报,但它确实有自己的一些边缘情况。单词边界匹配非单词字符(\W),它们将是任何不是a-zA-Z0-9_的字符。这意味着数字和下划线将被计为单词字符,像这样的场景将失败:

  • “你在想什么_are_?”
  • “是”在“哈哈,你不知道那些是4吗?”

如果你想要比这更准确的东西,你必须开始做英语语法解析,这是一个相当大的蠕虫(并假设正确使用语法,无论如何,这并不总是给定的)。

与SamGoody和Lego Stountroopr的评论相同。

如果你正在寻找一个PHP算法根据接近度/相关性对搜索结果进行排名的多个单词这里有一个仅使用PHP生成搜索结果的快速简便方法:

其他布尔搜索方法的问题,例如#0、#1、#2或#3

  1. 无法搜索多个单词
  2. 结果未排序

PHP方法基于向量空间模型tf-idf(术语频率-逆文档频率):

这听起来很困难,但出奇地容易。

如果我们想在一个字符串中搜索多个单词,核心问题是如何为每个单词分配权重?

如果我们可以根据它们在整个字符串中的代表性来对字符串中的术语进行加权,我们可以按最匹配查询的结果排序。

这就是向量空间模型的思想,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 normaliseforeach($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;}

案例1

$query = 'are';
$corpus = array(1 => 'How are you?',);
$match_results=get_similar_documents($query,$corpus);echo '<pre>';print_r($match_results);echo '</pre>';

结果

Array([1] => 0.52832083357372)

案例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>';

结果

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

案例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>';

结果

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

还有很多需要改进的地方但该模型提供了一种从自然查询中获得良好结果的方法,没有布尔操作符,例如strpos()preg_match()strstr()stristr()

NOTABENE

在搜索单词之前可以选择消除冗余

  • 从而减少索引大小并减少存储需求

  • 更少的磁盘I/O

  • 更快的索引和因此更快的搜索。

1.正常化

  • 将所有文本转换为小写

2.停用词消除

  • 删除文本中没有真正含义的单词(如“and”、“or”、“the”、“for”等)

3.字典替换

  • 用其他具有相同或相似含义的单词替换单词。(例如:将“饥饿”和“饥饿”替换为“饥饿”)

  • 可以执行进一步的算法措施(雪球)以进一步将单词简化为其基本含义。

  • 用其十六进制等价物替换颜色名称

  • 通过降低精度来减少数值是使文本正常化的其他方法。

资源

你需要使用相同/不相同的运算符,因为strpos可以返回0作为它的索引值。如果你喜欢三元运算符,请考虑使用以下运算符(我承认似乎有点落后):

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

您应该使用不区分大小写的格式,因此如果输入的值在smallcaps中,则无关紧要。

<?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 itwill goto else and will say NOT Found though it is found at 0th location.*/echo 'Contains word';}else{echo "does NOT contain word";}?>

在这里,考虑到大小写(小/大写),在heystack没有中找到针。

带有输出的PHPCode示例

简短的版本

$result = false!==strpos($a, 'are');

也许你可以使用这样的东西:

<?phpfindWord('Test all OK');
function findWord($text) {if (strstr($text, 'ok')) {echo 'Found a word';}else{echo 'Did not find a word';}}?>

为了找到一个“单词”,而不是出现一系列实际上可能是另一个单词的一部分的字母,以下是一个很好的解决方案。

$string = 'How are you?';$array = explode(" ", $string);
if (in_array('are', $array) ) {echo 'Found the word';}

令我印象深刻的是,这里没有一个使用strposstrstr和类似函数的答案提到多字节字符串函数(2015-05-08)。

基本上,如果你是难以找到具有特定于某些语言的字符的单词,例如德语、法语、葡萄牙语、西班牙语等(例如:äéôçoñ),你可能希望在函数mb_之前。因此,接受的答案将使用mb_strpos0或mb_strpos1(用于不区分大小写的匹配)代替:

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

如果您不能保证您的所有数据都是100%UTF-8,您可能希望使用mb_函数。

一篇很好的文章来理解为什么每个软件开发人员绝对,肯定必须了解Unicode和字符集(没有借口!) byJoel Spolsky

strpos函数工作得很好,但是如果你想在段落中检查一个单词,那么你可以使用PHPstripos函数。

例如,

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

查找字符串中不区分大小写的子字符串第一次出现的位置。

如果字符串中不存在单词,则它将返回false,否则它将返回单词的位置。

您可以使用strstr函数:

$haystack = "I know programming";$needle   = "know";$flag = strstr($haystack, $needle);
if ($flag){
echo "true";}

不使用内置函数:

$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 ";}

检查字符串是否包含特定单词?

这意味着字符串必须解析为单词(见下面的注释)。

执行此操作并指定分隔符的一种方法是使用preg_splitdoc):

<?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 eachforeach ($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');
?>

跑步给

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

备注:这里我们并不是指每个符号序列的单词。

单词的实际定义是PCRE正则表达式引擎,其中单词是仅由单词字符组成的子字符串,由非单词字符分隔。

“word”字符是任何字母或数字或下划线字符,也就是说,任何可以成为Perl“word”一部分的字符。这个字母和数字的定义由PCRE的字符控制表,如果正在进行特定于语言环境的匹配,则可能会有所不同(…)

如果你想检查字符串是否包含多个特定的单词,你可以这样做:

$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";}

例如,在发送电子邮件时,这对于避免垃圾邮件很有用。

可以使用以下函数检查字符串:

function either_String_existor_not($str, $character) {return strpos($str, $character) !== false;}

特定字符串的另一种解决方案:

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

您也可以使用strpos()函数。

它可以通过三种不同的方式完成:

 $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}

preg_match()

 if( preg_match("are",$a) === 1) {echo "true"; // are Found}

用途:

$text = 'This is a test';echo substr_count($text, 'is'); // 2
// So if you want to check if is exists in the text just put// in a condition like this:if (substr_count($text, 'is') > 0) {echo "is exists";}

在PHP中,验证字符串是否包含某个子字符串的最佳方法是使用像这样的简单帮助函数:

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

说明:

  • #0查找字符串中区分大小写的子字符串第一次出现的位置。
  • #0查找字符串中不区分大小写的子字符串第一次出现的位置。
  • myFunction($haystack, $needle) === FALSE ? FALSE : TRUE确保myFunction始终返回布尔值并修复子字符串索引为0时的意外行为。
  • $caseSensitive ? A : B选择#1#2来完成工作,具体取决于$caseSensitive的值。

输出:

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)

如果结果是>0,则使用#0检查的答案很多。但是由于if语句认为零是与false相同,您可以避免该检查并直接写入:

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

要检查没有是否存在,请添加!运算符:

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

用途:

$a = 'How are you?';if (mb_strpos($a, 'are')) {echo 'true';}

它执行多字节安全的strpos()操作。

更简单的选择:

return ( ! empty($a) && strpos($a, 'are'))? true : false;

您还可以使用内置函数#0#1以及多字节字符串#2#3的扩展。这些函数返回部分字符串,如果没有找到,则返回FALSE

  • strchr()-查找字符串的第一个匹配项(是#1的别名)。
  • strrchr()-查找字符串中字符的最后一次出现。

我认为一个好主意是使用mb_stpos

$haystack = 'How are you?';$needle = 'are';
if (mb_strpos($haystack, $needle) !== false) {
echo 'true';}

因为这个解决方案是区分大小写对所有Unicode字符都是安全的


你也可以这样做(索奇的反应还没有):

if (count(explode($needle, $haystack)) > 1) {
echo 'true';}

这个解决方案也是区分大小写安全的Unicode字符

除了你不要在表达中使用否定这增加了代码的易读性


这是另一个解决方案使用函数

function isContainsStr($haystack, $needle) {
return count(explode($needle, $haystack)) > 1;}
if (isContainsStr($haystack, $needle)) {
echo 'true';}