【问题标题】:PHP string replace match whole word in array [duplicate]PHP字符串替换匹配数组中的整个单词[重复]
【发布时间】:2018-05-07 17:03:21
【问题描述】:

我想将数组中包含的完整单词替换为对应的单词

$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);

我明白了

我的mousealogue 有一只鼠标和一本书

这不是我所期望的

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

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

【问题讨论】:

  • 如果您已经阅读了第一个答案的第一个答案:您也可以使用数组。是的,如果你用谷歌搜索的话,会有更好的重复。
  • 我尝试了最后一个响应,但得到的结果是:我的目录有一只鼠标和一本书。猫变成老鼠。
  • 关于副本的新答案,尽管您可能在回调中需要/i 标志和/或strtolower。 (懒得再找以前的问题了……)
  • @al404IT 您收到的答案会让您失望。它不值得绿勾,并且会教给未来的读者一个不准确/不稳定的方法。我可以为您的任务想出两种稳定的方法,但在重新打开之前无法发布它们。
  • 那些重复不考虑错误替换替换子串的可能性。

标签: php replace str-replace


【解决方案1】:

这应该对你有用

$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_callbackword boundary \b,因为除了\t 或任何其他单词之外,字符串中也可能有特殊字符。

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

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

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

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

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

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

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

的字符串

My catalog has a cat cat cat cat a\tdog and a phone

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

它将突出显示所有找到的匹配项,如下所示

我的目录有 cat cat cat cat dogphone

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

我们在这里所做的是,在第一个参数中,我们通过使用array_keys() 从给定数组中提取字符串中要匹配的单词来制作相同的regex,因为preg_replace_callback() 找到了匹配项字符串中的单词,它将它们传递给第二个参数中的callable anonymous function,并返回替换数组$arrWords中那些匹配项的替换单词只有一件事是use关键字,因为我们需要访问@987654359 @array 并从匹配的键返回相应的值,并且回调函数只有一个参数matches,因此将多个参数传递给回调函数的最简单方法是使用 'use' 关键字。我从 here 在用户贡献的注释部分得到了关于它的想法。

所以上面会输出

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

如果我们需要检查它是否保持不区分大小写,我们需要添加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.

资深会员提供的另一个案例是

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

输入

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

输出

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

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

【讨论】:

  • 哎呀,explode。只要文本不只包含空格,这就会变平,"My catalogue has a cat, and a\tphone"
  • @mickmackusa 嗯,你是对的我愿意删除这个答案,因为我没有也从未打算误导任何人,只是想帮助和学习,但是嘿读你的最后再次发表评论,您将退出**BE NICE POLICY**,您可以纠正他人而不会无礼,如果您愿意,可以保留自己的答案。
  • 固定解决方案不会替换替换的文本,将包含单词边界,并在替换后保留大写/小写字符串。使用这些变量进行测试:$txttest="The cat's mouse(named Mouse), cat (named Cat), and dog (named Giraffe) are in this catalogue."; $arrWords=["cat"=>"dog","dog"=>"mouse","mouse"=>"Mickey"]; 要非常小心。事实是,对于这项任务,SO 上可能已经有一个副本——SO 已经存在了很长一段时间。我目前没有足够的计算机时间来做更多事情。
  • 是的,这几乎是Wiktor 2 年前提供的重复/充分方法(最近由@mario 添加到关闭链接列表中)。您的方法仍然没有提供 OP 问题所需的不区分大小写的匹配。虽然我仍然认为应该删除此页面,但至少您正在借此机会提高自己的技能 - 所以这对您来说不是浪费时间。 OP 应该在发布问题之前进行研究。
  • 啊我只是解释它相反我让它区分大小写,看到你提到的那个帖子,我需要添加strtolower来实现它以及i,感谢您的输入@mickmackusa
猜你喜欢
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 2017-11-03
  • 2018-08-05
相关资源
最近更新 更多