PHP如何使用 Unicode 标准化移除字符串中的重音符号
在处理国际化文本、生成 URL 别名(Slug)或进行文本搜索时,我们经常需要将带有重音符号的字符(如 Á、ñ、ü)转换为其基础的 ASCII 字符(如 A、n、u)。
本文档将通过一个 PHP 示例函数 remove_accents,详细解释如何利用 Symfony 的 Polyfill 库和 Unicode 标准化(Normalization)来实现这一功能。
1. 代码示例
以下是核心功能的 PHP 代码实现:
1 | |
预期输出:
1 | |
2. 原理解析
这个函数的工作原理可以分为两个关键步骤:标准化 (Normalization) 和 **过滤 (Filtering)**。
步骤 1: Unicode 标准化 (Normalization Form D - NFD)
1 | |
- 什么是 NFD? Unicode 允许用两种方式表示同一个带重音的字符:
- **预组合字符 (Precomposed Character)**:例如
Á(U+00C1),它是一个单独的代码点。 - **分解字符 (Decomposed Characters)**:例如
A(U+0041) +´(U+0301,结合锐音符)。这两个代码点组合在一起显示时,看起来也是Á。
- **预组合字符 (Precomposed Character)**:例如
Normalizer::FORM_D的作用: 它将字符串中的所有“预组合字符”强制分解为“基字符”加上“组合字符”。- 输入:
Á - NFD 处理后:
A+◌́(非间距重音符)
- 输入:
步骤 2: 正则替换 (Regular Expression Replacement)
1 | |
- **
\p{Mn}**:这是一个 Unicode 属性转义。p代表 “Property” (属性)。Mn代表 “Mark, Nonspacing” (标记,非间距)。这正是 NFD 分解出来的那些重音符号、变音符所属的类别。
- **
+**:匹配一个或多个连续的非间距标记。 - **
/u**:这是一个非常重要的修饰符,告诉 PHP 的 PCRE 引擎将模式字符串视为 UTF-8 编码,这对于处理多字节的 Unicode 字符是必须的。
结果: 通过将所有属于 Mn 类别的字符替换为空字符串,我们就只剩下了纯净的基字符(例如 A),从而实现了“去除重音”的效果。
3. 依赖项
此脚本使用了 Symfony\Polyfill\Intl\Normalizer\Normalizer。这是一个 Polyfill 库,用于在系统缺少原生 PHP intl 扩展时提供 Normalizer 类。
如果你没有安装它,可以通过 Composer 安装:
1 | |
如果你的环境已经安装并启用了 PHP intl 扩展
PHP如何使用 Unicode 标准化移除字符串中的重音符号
https://kingjem.github.io/2025/12/04/php-处理重读字符/