PHP子字符串匹配整个单词

时间:2018-10-08 20:01:29

标签: php regex strpos

我正在尝试编写一个StringMatch函数,当可以在另一个字符串中找到一个字符串中的单词时返回true。唯一的例外是我不希望匹配复数和其他后缀之类的东西,并且我还想避免在单词加前缀时匹配。

以更直观的方式进行解释:

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()取得了一些基本的成功,我无法弄清楚当第二个字符串包含上述示例的后缀或前缀时如何返回“ 0”。

这是我要解决的方法:

function StringMatch($str1,$str2)
{
    if (SomeFunctionOrRegex($str1,$str2) !== false)
    {
        return(1);
    }
    else
    {
        return(0);
    }
}

也许有一个优美的正则表达式解决方案。我已经尝试过strpos(),但是对于我的需求来说还不够严格。

2 个答案:

答案 0 :(得分:3)

就像我在评论中所说的那样

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

Sandbox

Preg必须加引号,以免出现$str1可能包含诸如.之类的问题,该问题在Regex中是任何字符。

此外,您可以像这样删除标点符号

$str1 = preg_replace('/[^\w\s]+/', '', $str1);

例如:

echo StringMatch("apple watch.", "apple watch repairs"); // output 1

在不删除标点符号的情况下,它将返回0。无论是否重要,这取决于您。

Sandbox

更新

不匹配,例如:

//words out of order
echo StringMatch("watch apple", "new apple watch");     // output 1

简单的方法是内爆/爆炸:

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

Sandbox

您还可以跳过爆炸/爆炸并使用

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

Sandbox

但是,您当然不能计算单词数组,但可以计算|管道的数量,该数量比单词数量少1(因此为+1)。也就是说,如果您关心所有单词都匹配。

答案 1 :(得分:0)

  • 首先,正则表达式并不总是最好的解决方案。正则表达式需要编译。
  • 第二,您可以根据空间拆分单词,现在有了单个单词的数组。使用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");