php 8.3需用unicode正则\p{ishalfwidth}/\p{isfullwidth}配合mb_*函数区分全角/半角字符,strpos等函数不感知宽度,须结合preg_offset_capture与mb_strlen转换位置。

PHP 8.3 本身不提供直接“区分全角/半角字符”的内置搜索函数,但可以通过正则表达式配合 Unicode 属性类(\p{})精准识别并处理——关键不是搜索“位置”,而是**按字符宽度或编码属性做匹配筛选**。
用 \p{IsHalfwidth} 和 \p{IsFullwidth} 匹配特定宽度字符
Unicode 标准中定义了 \p{IsHalfwidth}(半宽)和 \p{IsFullwidth}(全宽)属性,PHP 8.3 的 PCRE2(启用 /u)完全支持:
- 匹配一个半角英文字母或数字(如 A、1):
preg_match('/^\p{IsHalfwidth}+$/u', $str) - 查找字符串中所有全角汉字、日文假名或全角标点:
preg_match_all('/\p{IsFullwidth}/u', $str, $matches),count($matches[0])即个数 - 判断是否混用了全角和半角空格:
preg_match('/[\x{3000}\s]/u', $str)(\x{3000}是全角空格,\s含 ASCII 空格、制表等)
实际搜索时按宽度逻辑过滤再定位
若需“找出第一个全角字符的位置”,不要硬套 strpos(它只认字节偏移),而应先提取目标字符再查索引:
- 获取首个全角字符及其在原串中的 UTF-8 字符位置(非字节偏移):
$pos = mb_strpos($str, $firstFullChar, 0, 'UTF-8');
其中$firstFullChar可由preg_match('/\p{IsFullwidth}/u', $str, $m)提取 - 更简洁方式:用
PREG_OFFSET_CAPTURE直接拿到匹配项的字节偏移,再转为字符位置:if (preg_match('/\p{IsFullwidth}/u', $str, $m, PREG_OFFSET_CAPTURE)) {<br> $byteOffset = $m[0][1];<br> $charPos = mb_strlen(substr($str, 0, $byteOffset), 'UTF-8');<br> }
业务中更实用的判断思路
多数场景不需要严格区分“全角/半角”,而是关注「视觉宽度」或「输入规范」:
- 限制昵称总显示宽度(如最多 12 个“中文宽度单位”):用
mb_strimwidth($str, 0, 12, '', 'UTF-8'),它自动按半角=1、全角=2 计算宽度 - 强制只允许半角输入(如密码框):用正则校验
^[ -~]*$(ASCII 可打印字符),而非长度判断 - 搜索时忽略全半角差异(如把“ABC”当作“ABC”匹配):先统一转换:
mb_convert_kana($str, 'a', 'UTF-8')(需 mbstring 扩展),再用stripos
核心在于:PHP 字符串搜索函数(strpos、strstr 等)操作的是字节或字符序列,不感知“宽度”;真正区分全半角,要靠 Unicode 属性正则 + 多字节安全函数协同完成。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











