
本文介绍如何使用 php 的 `preg_grep()` 配合正则表达式,精准筛选出**包含至少两个相同字母(无论位置是否相邻)**的字符串,适用于去重校验、模式识别等实际场景。
要实现“匹配任意字母重复出现至少两次(不强制连续)”的需求,关键在于捕获一个字母,并在后续内容中再次匹配该字母。此时应避免使用如 /a{2}/ 这类硬编码字符的写法,而改用反向引用(backreference)配合 Unicode 字母类 \p{L},确保兼容英文字母及多语言文字。
推荐正则表达式:
'/(\p{L}).*\1/'- (\p{L}):匹配并捕获任意一个 Unicode 字母(如 a, B, é, 中 等),存入捕获组 1;
- .*:匹配任意数量(包括零个)的非换行符字符(贪婪匹配);
- \1:反向引用,要求此处出现与捕获组 1 完全相同的字母。
✅ 示例代码(完整可运行):
$input_lines = ["asdf", "fdas", "asds", "d fm", "dfaa", "aaaa", "aabb", "aaabb"];
$result = preg_grep('/(\p{L}).*\1/', $input_lines);
print_r($result);输出结果:
立即学习“PHP免费学习笔记(深入)”;
Array
(
[2] => asds // s 出现两次(位置 0 和 2)
[4] => dfaa // a 出现两次(位置 2 和 3)
[5] => aaaa // a 多次重复
[6] => aabb // a 两次、b 两次
[7] => aaabb // a 至少两次
)⚠️ 注意事项:
- 若需仅匹配 ASCII 字母(如排除中文、带音标字符),可将 \p{L} 替换为 [a-zA-Z];
- .* 默认不跨行,若输入含换行符,请添加 s 修饰符:'/(\p{L}).*\1/s';
- 该模式不匹配数字或符号重复(如 "112" 或 "!!"),如需支持,可扩展为 '/([\p{L}\p{N}\W]).*\1/'(谨慎使用 \W,它包含空格和标点);
- 若要求严格两个相同字符且无更多重复(即恰好两次),需改用负向断言,例如 '/(\p{L})(?:(?!\1).)*\1(?!(?i)\1)/',但复杂度显著上升,一般场景无需过度约束。
总结:/(\p{L}).*\1/ 是简洁、高效、国际化友好的解决方案,兼顾可读性与实用性,适用于大多数“检测重复字母”的业务逻辑。











