截断Slug中间内容满足字符限制及正则匹配疑问求解
解决Slug长度限制与正则捕获组问题
一、正则匹配结果多元素的原因
你写的正则里,()是捕获组,每个捕获组会把匹配到的内容单独存入$matches数组:
$matches[0]:整个正则匹配到的完整字符串$matches[1]/[2]/[3]:分别对应正则里三个()包裹的内容
如果只想拿到完整匹配结果,要么去掉所有括号,要么把括号改成非捕获组(?:...),比如/-in-\d{5}-(?:.*)-(?:.*)-(?:\d*)/,这样$matches里就只有完整匹配项了。
二、实现Slug长度控制(完整保留尾部位置信息)
核心思路是先拆分slug的固定前缀、职位文本、尾部位置文本,再计算职位部分的可占用长度,最后按需截断职位部分并拼接。
步骤1:拆分Slug各部分
用正则拆分出/job/前缀、中间职位内容、从-in-+5位邮编开始的尾部内容:
$slug = '/job/hello-this-is-my-job-posting-for-a-daycare-im-looking-for-in-91770-rosemead-california-12345'; preg_match('/^(\/job\/)(.*?)(-in-\d{5}-.*)$/', $slug, $parts); $prefix = $parts[1]; // '/job/' $jobContent = $parts[2]; // 职位文本部分 $locationTail = $parts[3]; // 尾部位置+ID部分
步骤2:计算可分配给职位文本的长度
总限制150字符,先算出必须保留的长度(前缀+尾部),剩余长度就是职位文本能占用的最大值:
$maxTotalLen = 150; $reservedLen = strlen($prefix) + strlen($locationTail); $maxJobLen = $maxTotalLen - $reservedLen; // 处理边界:如果前缀+尾部已经超150,根据业务调整(比如报错) if ($reservedLen > $maxTotalLen) { $finalSlug = $slug; // 或者抛出异常 } else { if (strlen($jobContent) <= $maxJobLen) { $finalSlug = $prefix . $jobContent . $locationTail; } else { // 拆分职位文本为单词数组 $jobWords = explode('-', $jobContent); // 循环删除中间单词,直到长度符合要求 while (strlen(implode('-', $jobWords)) > $maxJobLen && count($jobWords) > 1) { // 删除中间位置的单词(符合你"从中间删单词"的需求) array_splice($jobWords, floor(count($jobWords)/2), 1); } // 拼接最终slug $truncatedJob = implode('-', $jobWords); $finalSlug = $prefix . $truncatedJob . $locationTail; } } echo $finalSlug;
关键细节
- 拆分正则用
.*?非贪婪匹配,确保职位文本不会包含尾部内容。 - 删单词的逻辑可以按需调整:如果要删开头就用
array_shift(),删结尾用array_pop(),当前代码是删中间单词。 - 如果只剩最后一个单词仍超长,可以根据需求截断单词本身(比如
substr($truncatedJob, 0, $maxJobLen))。
内容的提问来源于stack exchange,提问作者David Pham
相关产品推荐
相关产品推荐

