PHP哈希标签提取函数处理含标点符号哈希标签的问题修复咨询
PHP哈希标签提取函数处理含标点符号哈希标签的问题修复咨询
嘿,我来帮你搞定这个哈希标签提取的问题!
首先得说,你原函数的思路没问题,但没考虑到哈希标签会和标点符号连在一起——比如#rock,会被当成一个完整单词,截取后得到的rock,包含逗号,自然通不过你那只允许字母数字的正则校验,所以提取失败。你之前尝试的全局替换非字母数字字符,会把文本里的空格也删掉,反而破坏了结构,当然没用啦。
下面给你两种改进方案,都能完美解决这个问题,还顺便修复了原函数末尾多逗号的小bug:
方案一:改进原有循环逻辑
我们可以给每个单词单独做正则匹配,直接提取#后面的有效字母数字部分,不管后面有没有标点:
function getHashtags ($text) { $text = explode(" ", $text); $hashtags = []; // 用数组存储标签,避免末尾多余逗号 // 正则匹配#开头,后面跟着1-11位字母数字的内容 $hashReg = "/#([a-zA-Z0-9]{1,11})/"; foreach ($text as $word) { // 如果单词里包含符合要求的哈希标签,就提取出来 if (preg_match($hashReg, $word, $matches)) { $hashtags[] = $matches[1]; } } // 用逗号拼接数组元素,自动避免末尾逗号 return implode(",", $hashtags); }
测试一下你的例子:
$post = "#rock, #music, is good"; echo getHashtags($post); // 输出:rock,music
方案二:用正则全局匹配(更高效简洁)
不用拆分文本,直接用preg_match_all一次性提取所有符合要求的哈希标签,还能避免误匹配比如abc#rock这种非独立标签的情况:
function getHashtags ($text) { $hashtags = []; // 正则解释: // (?<!\w) 负向后瞻,确保#前面不是字母数字(避免误匹配连在单词后的#) // #([a-zA-Z0-9]{1,11}) 匹配#开头,后面1-11位字母数字的标签,捕获标签内容 preg_match_all('/(?<!\w)#([a-zA-Z0-9]{1,11})/', $text, $matches); if (!empty($matches[1])) { $hashtags = $matches[1]; } return implode(",", $hashtags); }
测试复杂场景:
$post = "#rock, #music. is #great! #toolonghashtag123"; echo getHashtags($post); // 输出:rock,music,great
这里#toolonghashtag123因为长度超过11,会被自动过滤,完全符合你原函数的要求。
备注:内容来源于stack exchange,提问作者Max Njoroge
相关产品推荐
相关产品推荐

