PHP中实现多关键词正则替换:仅替换每个关键词的首次匹配

这是一个陷阱。
不信可以直接用preg_replace替换所有匹配,而不区分第一个匹配。

结合状态管理使用preg_replace_callback,只替换每个关键字的第一个匹配项,例如:
php $string = '我是一名游戏玩家,喜欢玩电子游戏。
电子游戏很棒。
我已经玩游戏很长时间了。
我喜欢和其他玩家朋友一起出去玩。
$keywordsToMatch = ['玩家', '游戏']; $replacementUrlBase = "https://example.com/tag/";
$escapedKeywords = array_map(function($keyword) { 返回 preg_quote($keyword, '/'); }, $keywordsToMatch);
$patttern = '/b(?' . implode('|', $escapedKeywords) . ')b/i';
$usedKeywords = []; $finalString = preg_replace_callback($pattern, function($matches) use ($usedKeywords, $replacementUrlBase) { $currentKeyword = $matches['关键字']; $normalizedKeyword = strtolower($currentKeyword); if (in_array($normalizedKeyword, $usedKeywords, true)) { 返回$当前关键字; } $usedKeywords[] = $normalizedKeyword; $href = $replacementUrlBase. urlencode($当前关键字); 返回“{$currentKeyword}”; }, $string);
echo $finalString;
结论:
我是一名游戏玩家,喜欢玩电子游戏。
电子游戏很棒。
我已经玩游戏很长时间了。
我喜欢和其他玩家朋友一起出去玩。

不要这样做,直接替换所有相关元素即可,效率低下,效果也不理想。

求用php正则表达式来替换字符的写法。

说实话,大量使用正则表达式确实很有趣。
我刚刚接受了客户服务系统的审查。
当时团队里有一个老头,每天都对正则表达式发疯。
负责处理用户提交的地址信息,自动对省市进行排序。
想想看,“北京市海淀区中关村大街1 号”和“上海普陀区长寿路1 2 3 弄”只要按空格键肯定不行——北京的叫“市辖区”,上海的叫“区”,而且中文名字和数字混在一起,太可怕了。

这时候我想到了一些技巧。
他先用\s+进行分词,然后发现北京、上海等直辖市后面直接是区,但是普通省份可能有地级市后面是区。
他对【北、津、沪、渝】【省市】进行了配对。
说实话,当时看起来有点极端:如果用户输入“河北、北京、天津、上海、重庆”,系统不就乱套了吗?好在地址格式非常规范,所以基本上没有发生什么事情。

后来我遇到了一个更了不起的人。
有一个小区名称中带有“楼”和“花园”,如“香江花园三期”。
你需要分离“第三阶段”。
老哥是直接去【大中小】的【\s\S】+了吗?问题我一看就惊呆了:[\s\S]+?这个鬼画标志是什么意思?他解释说\s对应空格,\S对应非空格,加一个+表示“一个或多个”,而?它是一种“非贪婪模式”,这意味着“停止匹配第一个‘点’”。
这里用“香江花园三期”可以精确地消除“三期”,而“现代城市广场”可以消除“广场”——尽管那个东西可能不是用户想要的。

最好的办法是处理特殊符号。
需要对用户输入的身份证号进行过滤,但有的人直接将身份证号复制粘贴到业务模板中,得到的结果都是1 2 3 4 5 6 7 8 9 01 2 3 4 5 6 7 8 9 0。
我哥说很简单,用\d{1 7 }[\dX]即可:身份证号的1 7 位都是数字,最后一位可以是数字,也可以是X。
事实证明,用户更狠。
有人用Excel自动生成身份证号码,直接复制粘贴成“1 2 3 4 5 6 7 8 9 01 2 3 4 5 6 7 8 9 01 2 3 4 5 6 7 8 9 0”之类的。
老人当时脸就绿了,最后只能加上{1 7 ,1 8 },意思就是“1 7 到1 8 位,多了也没关系”。

我自己没跑过,但是后来看了测试报告。
记得审核后,地址解析准确率从9 2 %提升到9 7 %左右,但身份证号识别率仍然停留在9 5 %。
测试说“用户太奇怪了”。
哥哥最后的总结是:“正则表达式,核心无非就是两个字:反向推理。
想想用户最有可能怎么填写,然后倒着写规则。

PHP正则表达式如何替换像这样的案例的

哎呀,这个正则表达式替换的事情其实很简单。
你看,第一个例子中的字符串是“龙飞剑/龙飞剑电视剧”,分隔符后面的内容需要替换。
使用正则表达式“~/.?$~”。
这意味着从分隔符替换到字符串末尾。
当我写这段代码时,我不明白这个正则表达式从何而来。
我刚刚看到其他人这样使用它,所以我也尝试了一下,嘿,它确实有效。

第二个例子,字符串是“龙门飞剑/龙飞剑电视剧版”,这个字符串有点复杂。
使用正则表达式“~/.?(?=|$)~”。
这次我们不是直接替换到最后,而是需要找到满足条件的分隔符,然后将分隔符后面的所有内容替换掉。
这里的“(?=|$)”是一个前向断言,意思是“要么是这里的分隔符,要么是字符串的结尾”。
这样,无论分隔符后面有多少内容,都可以立即替换。

说实话,像这样的东西用正则表达式替换关键要看情况。
例如,必须考虑分隔符后面是否有空格或其他特殊字符。
不过,一般来说,使用正则表达式来替换比手动更改要方便得多。