PHP 匹配整个单词的子串
PHP substring matching whole words
我正在尝试编写一个 StringMatch 函数,当一个字符串中的单词可以在另一个字符串中找到时,该函数 return 为真。例外是我不想匹配复数和其他后缀之类的东西,我也想避免在单词有前缀时进行匹配。
更直观的解释:
apple watch - apple watches (no match)
apple watch - apple watch repairs (match)
apple watch - new apple watch (match)
apple watch - pineapple watch (no match)
我想是这样的:
echo StringMatch("apple watch", "apple watches"); // output 0
echo StringMatch("apple watch", "apple watch repairs"); // output 1
echo StringMatch("apple watch", "new apple watch"); // output 1
echo StringMatch("apple watch", "pineapple watch"); // output 0
我在 strpos() 方面取得了一些基本的成功,当第二个字符串包含上述示例中的后缀或前缀时,我无法弄清楚如何 return “0”。
这是我尝试解决的方法:
function StringMatch($str1,$str2)
{
if (SomeFunctionOrRegex($str1,$str2) !== false)
{
return(1);
}
else
{
return(0);
}
}
也许有一个优雅的正则表达式解决方案。我试过 strpos() 但它不够严格,无法满足我的需要。
就像我在评论里说的那样
function StringMatch($str1,$str2)
{
return preg_match('/\b'.preg_quote($str1,'/').'\b/i', $str2);
}
echo StringMatch("apple watch", "apple watches"); // output 0
echo "\n";
echo StringMatch("apple watch", "apple watch repairs"); // output 1
echo "\n";
echo StringMatch("apple watch", "new apple watch"); // output 1
echo "\n";
echo StringMatch("apple watch", "pineapple watch"); // output 0
echo "\n";
输出:
0
1
1
0
Preg 引用是必要的,以避免 $str1
可能包含 .
之类的问题,在正则表达式中它是任何字符。
此外,您可以像这样去除标点符号
$str1 = preg_replace('/[^\w\s]+/', '', $str1);
例如:
echo StringMatch("apple watch.", "apple watch repairs"); // output 1
如果不删除标点符号,这将 return0。重要与否取决于您。
更新
乱序匹配,例如:
//words out of order
echo StringMatch("watch apple", "new apple watch"); // output 1
简单的方法是implode/explode:
function StringMatch($str1,$str2)
{
//use one or the other
$str1 = preg_replace('/[^\w\s]+/', '', $str1);
//$str1 = preg_quote($str1,'/');
$words = explode(' ', $str1);
preg_match_all('/\b('.implode('|',$words).')\b/i', $str2, $matches);
return count($words) == count($matches[0]) ? '1' : '0';
}
您也可以跳过 explode/implode 并使用
$str1 = preg_replace('/\s/', '|', $str1);
哪个可以和另一个组合preg_replace
$str1 = preg_replace(['/[^\w\s]+/','/\s/'], ['','|'], $str1);
或者一起
function StringMatch($str1,$str2)
{
$str1 = preg_replace(['/[^\w\s]+/','/\s/'], ['','|'], $str1);
preg_match_all('/\b('.$str1.')\b/i', $str2, $matches);
return (substr_count($str1, '|')+1) == count($matches[0]) ? '1' : '0';
}
但是当然你不能计算单词数组,但是你可以计算 |
管道的数量,它比单词的数量少 1(因此是 +1)。也就是说,如果您关心所有单词是否匹配。
- 首先,正则表达式并不总是最好的解决方案。正则表达式需要编译。
- 其次,您可以根据 space 拆分单词,现在您有一组单独的单词。使用 in_array() 并检查大海捞针中的每个单词。
代码:
<?php
function StringMatch($needle,$haystack){
$domain_of_words = explode(" ",$haystack);
$words = explode(" ",$needle);
foreach($words as $each_word){
if(!in_array($each_word,$domain_of_words,true)){
return 0;
}
}
return 1;
}
echo StringMatch("apple watch","apple watches repairs"),"<br/>";
echo StringMatch("apple watch","apple watch repairs");
我正在尝试编写一个 StringMatch 函数,当一个字符串中的单词可以在另一个字符串中找到时,该函数 return 为真。例外是我不想匹配复数和其他后缀之类的东西,我也想避免在单词有前缀时进行匹配。
更直观的解释:
apple watch - apple watches (no match)
apple watch - apple watch repairs (match)
apple watch - new apple watch (match)
apple watch - pineapple watch (no match)
我想是这样的:
echo StringMatch("apple watch", "apple watches"); // output 0
echo StringMatch("apple watch", "apple watch repairs"); // output 1
echo StringMatch("apple watch", "new apple watch"); // output 1
echo StringMatch("apple watch", "pineapple watch"); // output 0
我在 strpos() 方面取得了一些基本的成功,当第二个字符串包含上述示例中的后缀或前缀时,我无法弄清楚如何 return “0”。
这是我尝试解决的方法:
function StringMatch($str1,$str2)
{
if (SomeFunctionOrRegex($str1,$str2) !== false)
{
return(1);
}
else
{
return(0);
}
}
也许有一个优雅的正则表达式解决方案。我试过 strpos() 但它不够严格,无法满足我的需要。
就像我在评论里说的那样
function StringMatch($str1,$str2)
{
return preg_match('/\b'.preg_quote($str1,'/').'\b/i', $str2);
}
echo StringMatch("apple watch", "apple watches"); // output 0
echo "\n";
echo StringMatch("apple watch", "apple watch repairs"); // output 1
echo "\n";
echo StringMatch("apple watch", "new apple watch"); // output 1
echo "\n";
echo StringMatch("apple watch", "pineapple watch"); // output 0
echo "\n";
输出:
0
1
1
0
Preg 引用是必要的,以避免 $str1
可能包含 .
之类的问题,在正则表达式中它是任何字符。
此外,您可以像这样去除标点符号
$str1 = preg_replace('/[^\w\s]+/', '', $str1);
例如:
echo StringMatch("apple watch.", "apple watch repairs"); // output 1
如果不删除标点符号,这将 return0。重要与否取决于您。
更新
乱序匹配,例如:
//words out of order
echo StringMatch("watch apple", "new apple watch"); // output 1
简单的方法是implode/explode:
function StringMatch($str1,$str2)
{
//use one or the other
$str1 = preg_replace('/[^\w\s]+/', '', $str1);
//$str1 = preg_quote($str1,'/');
$words = explode(' ', $str1);
preg_match_all('/\b('.implode('|',$words).')\b/i', $str2, $matches);
return count($words) == count($matches[0]) ? '1' : '0';
}
您也可以跳过 explode/implode 并使用
$str1 = preg_replace('/\s/', '|', $str1);
哪个可以和另一个组合preg_replace
$str1 = preg_replace(['/[^\w\s]+/','/\s/'], ['','|'], $str1);
或者一起
function StringMatch($str1,$str2)
{
$str1 = preg_replace(['/[^\w\s]+/','/\s/'], ['','|'], $str1);
preg_match_all('/\b('.$str1.')\b/i', $str2, $matches);
return (substr_count($str1, '|')+1) == count($matches[0]) ? '1' : '0';
}
但是当然你不能计算单词数组,但是你可以计算 |
管道的数量,它比单词的数量少 1(因此是 +1)。也就是说,如果您关心所有单词是否匹配。
- 首先,正则表达式并不总是最好的解决方案。正则表达式需要编译。
- 其次,您可以根据 space 拆分单词,现在您有一组单独的单词。使用 in_array() 并检查大海捞针中的每个单词。
代码:
<?php
function StringMatch($needle,$haystack){
$domain_of_words = explode(" ",$haystack);
$words = explode(" ",$needle);
foreach($words as $each_word){
if(!in_array($each_word,$domain_of_words,true)){
return 0;
}
}
return 1;
}
echo StringMatch("apple watch","apple watches repairs"),"<br/>";
echo StringMatch("apple watch","apple watch repairs");