PHP字符串替换匹配数组中的整个单词

时间:2017-11-23 17:02:25

标签: php replace str-replace

我想用等效的

替换数组中包含的完整单词
$arrWords = array(
   "cat" => "dog",
   "dog" => "mouse",
   "phone" => "book"
);

$txttest = "My catalogue has a cat and a phone";
猫应该成为狗而不是老鼠,并且必须不区分大小写

本文

  

我的目录有猫和手机

应该成为

  

我的目录中有一只狗和一本书

用这个

$result = str_replace(array_keys($arrWords), array_values($arrWords), $txttest);

我得到了

  

我的鼠标有一个鼠标和一本书

并不是我所期待的

编辑:我的问题已被标记为重复 PHP string replace match whole word

在那个问题中,有必要只用一个单词替换另一个单词,而是我需要替换多个单词,搜索第一次出现的数组(键)并替换为数组(值)

1 个答案:

答案 0 :(得分:2)

这应该对你有用

$arrWords = array(
    "cat" => "dog",
    "dog" => "mouse",
    "phone" => "book"
 );

 $txttest = "My catalogue has a cat and a phone";
 $stringArr =   explode(' ',$txttest);

foreach($stringArr as $k=>$v){
    if(array_key_exists($v,$arrWords)){
        $stringArr[$k]=$arrWords[$v];
    }
}
echo implode(' ',$stringArr);

<击>

修改

根据给定的情况替换字符串

My catalog has a cat and a phone

使用以下数组匹配键并替换为相应的值

$arrWords = array(
        "cat" => "dog",
        "dog" => "mouse",
        "phone" => "book"
     );

由于存在与键匹配的特定值,如果我们在上面的数组的for循环中使用preg_replace,我们的替换字符串很可能会相互替换,

可能的嫌疑人("cat" => "dog","dog" => "mouse")

在这种情况下,更好的替代方案是preg_replace_callback word boundary \b用于此类要求,因为除了像\t之类的字词外,字符串中也可能包含特殊字符即TAB或任何其他。

所以理想情况下,上面提供的原始解决方案不应该(实际上永远不会)使用,并且不是真正的解决方案,因为当有特殊字符时会失败

实际应该做的是首先创建一个正则表达式

  

应该使用包含内部捕获组的单词边界   所有要匹配的单词作为替代(使用OR运算符)。

因此,如果我将上述语句转换为正则表达式,请记住给定的搜索和替换数组$arrWords就好了。

/\b(cat|dog|phone)\b/gi

g修饰符最后是global pattern flag,它确保所有匹配(在第一次匹配后不返回)和i用于不区分大小写的匹配。在g函数中使用时我们可以省略preg_replace_callback()修饰符,因为此函数的第4个参数将处理它。

因此,如果我将regex添加到任何在线正则表达式实用程序并提供类似

的字符串

<强> My catalog has a cat cat cat cat a\tdog and a phone

(请注意,使用在线实用程序时,您应该在将字符串写入在线正则表达式编辑器时将实际TAB删除\ t以将其检测为特殊字符或\ t \ t \ t)

它将突出显示如下所示的所有匹配

我的目录中有cat cat cat cat一个dog和一个phone

a之后的空格是因为TAB) 现在需要更换它们并且在替换上面的语句之后应该转换为

<强> My catalog has a dog dog dog dog a mouse and a book

所以现在来了preg_replace_callback()和回调函数,它将完成更换并处理不交换/替换替换密钥的技巧。

$r = preg_replace_callback(
    "/\b(".implode("|",array_keys($arrWords)).")\b/i",
    function($matchingPharse) use ($arrWords) {
        return strtolower($arrWords[strtolower($matchingPharse[0])]);
    },
    $txttest
);

我们在这里做的是,在第一个参数中,我们通过使用regex从给定数组中提取要在字符串中匹配的单词,使array_keys()变为preg_replace_callback(),如{{ 1}}在字符串中找到匹配的单词,它将它们传递给第二个参数中的callable anonymous function,并在替换数组$arrWords中返回那些匹配的替换单词,只有一个是新的{{1} }}关键字,因为我们需要访问use数组并从匹配的键返回相应的值,而回调函数只有一个参数$arrWords所以最简单的方法是将多个参数传递给回调函数使用'use'关键字。我从here下的User Contributed Notes部分了解了它。

所以上面会输出

我的目录中有一只狗狗狗,一只老鼠和一本书

如果我们需要检查它是否保留不区分大小写,我们需要添加matches Feed

INPUT

<强> i

输出

<强> The cat's mouse(named Mouse), cat (named Cat), and dog (named Giraffe) are in this catalog.

高级成员提供的另一个案例是

The dog's mouse(named Mouse), dog (named dog), and mouse (named Giraffe) are in this catalog.

INPUT

<强> $arrWords=["cat"=>"dog","dog"=>"mouse","mouse"=>"Mickey"];

输出

<强> The cat's mouse(named Mouse), cat (named Cat), and dog (named Giraffe) are in this catalog.

我与社区的一名高级成员进行了讨论,他指导我在原始答案中的错误信息的严重性,这可能引导其他人走向错误的方向,而SO,我或该社区的任何其他成员都不打算这样做要做,所以我试图改进答案,如果他打算使用我以前的答案,请求OP所有者遵循这种方法。我为在开始时提供一个糟糕的解决方案而道歉。