
本文介绍如何使用 preg_match_all 配合合理正则表达式,从任意文本中批量提取符合西班牙规范(4位数字+3位字母,允许空格或短横分隔)的车牌号,并统一清洗为大写无分隔符的标准格式。
本文介绍如何使用 `preg_match_all` 配合合理正则表达式,从任意文本中批量提取符合西班牙规范(4位数字+3位字母,允许空格或短横分隔)的车牌号,并统一清洗为大写无分隔符的标准格式。
要正确解析包含多个西班牙车牌号的混合字符串(如 "1234-ABC 2345 rBC 9998DDD 9657 lJi"),关键在于:避免使用 preg_split 或贪婪量词匹配整个字符串,而应采用非捕获、可重复、独立匹配的思路,用 preg_match_all 精准定位每个合法车牌单元。
原始正则 (\d{4})( *)(-*)( *)([a-zA-Z]{3}) 存在两个核心问题:
- 它依赖固定分组结构,未将分隔符(空格/短横)作为可选中间字符处理;
- 使用
+量词配合preg_match会导致只返回一次“整体匹配”,无法分离多个车牌。
✅ 推荐正则表达式:
'/(\d{4}[-\s]*[a-z]{3})/i'说明:
立即学习“PHP免费学习笔记(深入)”;
-
\d{4}:严格匹配 4 位数字; -
[-\s]*:匹配零个或多个短横-或空白符(含空格、制表符等); -
[a-z]{3}:匹配 3 个英文字母,i修饰符使其不区分大小写; - 整体用括号包裹形成捕获组,便于
preg_match_all提取完整匹配项。
配合 PHP 实现完整提取与标准化流程如下:
<?php
$input = "1234-ABC 2345 rBC 9998DDD 9657 lJi";
// 步骤1:全局匹配所有符合模式的子串
preg_match_all('/(\d{4}[-\s]*[a-z]{3})/i', $input, $matches);
// 步骤2:$matches[0] 是完整匹配结果数组(推荐用此索引)
$plates = $matches[0] ?? [];
// 步骤3:清洗每个车牌 — 移除空格/短横,转为大写
$cleaned = array_map(function($plate) {
return strtoupper(preg_replace('/[-\s]+/', '', $plate));
}, $plates);
print_r($cleaned);
// 输出:
// Array
// (
// [0] => 1234ABC
// [1] => 2345RBC
// [2] => 9998DDD
// [3] => 9657LJI
// )
?>⚠️ 注意事项:
-
不要用
array_shift($matches):它会破坏$matches结构,且$matches[0]才是目标结果数组(即所有完整匹配项),而非$matches[1]; - *避免 `+
贪婪组合**:如(...)*+易导致回溯灾难或漏匹配,preg_match_all` 天然支持多次独立匹配,无需手动构造“重复组”; -
边界控制(进阶建议):若需防止误匹配(如
"12345ABC"中的"2345ABC"),可在正则两端添加单词边界\b:/\b\d{4}[-\s]*[a-z]{3}\b/i,但需注意西班牙车牌常出现在纯文本中,无明确标点分隔时慎用; -
字母合法性:西班牙实际车牌字母不含
I,O,U,Ñ等(避免混淆数字或特殊字符),如需严格校验,可将[a-z]{3}替换为[A-HJ-NP-TV-Z]{3}(忽略大小写)。
该方案简洁、健壮、可读性强,适用于表单批量解析、日志提取、OCR 后处理等真实场景。



















