本文介绍如何在php中通过正则表达式智能分词,将血型等固定多词组合(如“a positive”“o negative”)视为不可分割的语义单元,避免传统空格切分导致的误匹配问题。
在构建血液捐献者搜索系统时,一个常见却关键的挑战是:如何让语义上紧密关联的多词(如血型名称)不被简单按空格拆散?例如,用户输入 "o negative blood donor in khulna",若直接用 explode(" ", $keyword) 切分,会得到 ['o', 'negative', 'blood', 'donor', 'in', 'khulna'] —— 这导致 SQL 中对 'o' 的模糊匹配命中所有含字母 o 的姓名(如 rony, jony, tony),严重降低结果准确性。
根本问题在于:"o negative" 是一个完整、不可分割的业务实体(血型),应被当作一个“单词”处理,而非两个独立关键词。 解决方案不是硬编码所有血型,而是使用语义感知的正则分词,优先识别预定义模式(如 [a|b|o] [positive|negative]),再捕获其余普通词。
以下 PHP 代码使用精准正则表达式,自动合并血型短语,并保留其余词汇:
$keyword = "o negative blood donor in khulna"; // 正则说明: // (?i) → 忽略大小写 // \b[abo]\s+ → 匹配字首边界 + a/b/o + 一个或多个空白符 // (?:posi|nega)tive\b → 非捕获组匹配 "positive" 或 "negative" + 字尾边界 // | → 或 // \S+ → 匹配任意非空白字符序列(兜底捕获其他词) $pattern = '/(?i)\b[abo]\s+(?:posi|nega)tive\b|\S+/'; preg_match_all($pattern, $keyword, $matches); $keyword_array = $matches[0]; print_r($keyword_array); // 输出: // Array // ( // [0] => o negative // [1] => blood // [2] => donor // [3] => in // [4] => khulna // )
$placeholders = str_repeat('?,', count($keyword_array) - 1) . '?';
$stmt = $pdo->prepare("... WHERE bg.group_name LIKE ? OR ...");
foreach ($keyword_array as $term) {
$stmt->bindValue($param++, "%{$term}%", PDO::PARAM_STR);
}通过这种正则分词策略,你不仅能精准命中 "o negative" 血型的捐献者(仅返回 ID=3 的 tony),还能确保搜索逻辑可维护、可扩展——让技术真正服务于医疗场景的语义严谨性。