HTML 字符实体速查表 - HTML 特殊符号编码大全
动态生成的 HTML 里,&、<、> 三个字符一旦漏转义,轻则页面结构变形、重则变成 XSS 入口;反过来,看不懂源码里满屏的 & 也常常卡住排查。这张表按基础字符、常用符号、货币、箭头、数学、希腊字母分类,每个符号同时给出命名实体与十六进制数字式两种写法,便于按输出目标选型。判断依据是输出环境:写入 HTML 正文用命名实体便于人读,写进 JSON、JS 字符串或只支持有限字符集的旧系统时用数字式 &#x...; 更保险;而整页已声明 UTF-8 编码的情况下,像 ©、→、α 这类符号直接写原字符通常才是最简洁的写法。什么时候翻它:处理用户输入、拼邮件模板、修复显示成乱码的字符、或者把某个符号从一个页面搬到另一个而不丢格式。
基础字符 6
& 或 &< 或 <> 或 >" 或 "' 或 ' 或  常用符号 7
© 或 ©® 或 ®™ 或 ™° 或 °± 或 ±× 或 ×÷ 或 ÷货币符号 5
¢ 或 ¢£ 或 £¥ 或 ¥€ 或 €₹箭头符号 5
← 或 ←↑ 或 ↑→ 或 →↓ 或 ↓↔ 或 ↔数学符号 8
∀ 或 ∀∃ 或 ∃∞ 或 ∞∑ 或 ∑√ 或 √≠ 或 ≠≤ 或 ≤≥ 或 ≥希腊字母 7
α 或 αβ 或 βγ 或 γδ 或 δπ 或 πσ 或 σω 或 ω命令示例
按固定顺序一次转义 & < >,避免实体被二次替换
node -e "
const line = 'a<b && c>d; \"q\"'
const safe = line
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
console.log(safe)"
& 排在链首是关键:如果先把 < 换成 <,随后处理 & 时新产生的 & 会被再次替换,页面里就会出现 &amp; 而不是尖括号。这里保留了双引号,因为在双引号包裹的属性之外它无需转义;若目标是 " 包裹的属性,还需要再补一次把双引号换成 " 的替换。
输出
a<b && c>d; "q"
反向还原:把一段含命名与数字实体的 HTML 文本解码回原字符
python -c "import html; print(html.unescape('Tom & Jerry <3 © © α →'))"排查乱码时最有用的一步:先确认乱码源头是不是被转义了两次。© 与 © 都解码成 ©,α 与 α 都解码成 α——如果 unescape 之后屏幕上还残留 & 这类字面文本,那就是上游已经做过一次转义,需要在那一层修,而不是在这里再解一次。
输出
Tom & Jerry <3 © © α →
用 grep -P 找出漏写分号或未转义的裸 &
printf 'a & b © c © d €
' > page.html
grep -oP '&[#a-zA-Z0-9]+;?' page.html
grep -nP '&(?!amp;|lt;|gt;|quot;|apos;|nbsp;|copy;|reg;|trade;|deg;|plusmn;|times;|divide;|cent;|pound;|yen;|euro;|larr;|uarr;|rarr;|darr;|harr;|forall;|exist;|infin;|sum;|radic;|ne;|le;|ge;|alpha;|beta;|gamma;|delta;|pi;|sigma;|omega;|#[0-9]+;|#x[0-9a-fA-F]+;)' page.html第一条把页面上所有形如实体的片段列出来,人工扫一遍就能发现 © 这种缺分号的写法;第二条是反向断言,正向不允许列表之外还有 & 开头的片段,因此命中就说明要么实体名不在本表、要么分号缺失、要么是漏转义的裸 &。白名单要随项目实际用到的实体扩充,否则正常实体也会被报出来。
输出
& © © € 1:a & b © c © d €
从码点反查数字实体,十进制与十六进制两种写法一次生成
node -e "
for (const ch of ['©', '€', 'α', '→', '∞']) {
console.log(ch, '&#' + ch.codePointAt(0) + ';', '&#x' + ch.codePointAt(0).toString(16) + ';')
}
"本表货币与箭头、希腊字母分组里列出的十进制数字式,就是这样从码点算出来的:字符码点即十进制数字,十进制转十六进制即 x 形式。记忆成本高的是码点本身而不是写法——© 与 © 等价,€ 与 € 等价,遇到表里没有的符号时按这个办法现场推导比翻表快。
输出
© © © € € € α α α → → → ∞ ∞ ∞
常见坑与注意事项
- 漏转义 & < > 会让页面结构由数据决定:用户输入里一个未转义的 < 就可能伪造出标签或属性,这是最典型的 XSS 入口。
- 转义顺序必须是 & 优先。逐字符替换时若先处理 <、后处理 &,新产生的 & 会被二次替换成 &amp;,页面上直接出现实体字面文本。
- 输出机器可读数据(JSON、JS 字符串、邮件模板)时统一补分号;© 省略分号在部分老解析器与二次处理链路里会被吃掉或截断。
- 是「禁止换行」的语义,不是间距工具。拿它当 margin 用会让排版规则散进正文,并被屏幕阅读器额外朗读;纯间隙用 CSS 的 gap 或 margin。
- 单次转义后就不要再来一遍。已转义内容再次过转义函数会把 & 变成 &amp;;渲染前先判断数据是否已经过上游转义层。
提示
- HTML 中显示 < > & 等字符必须用实体,否则会被解析为标签或实体开始。
- 数字实体(&#数字;)兼容性更好,命名实体(&名称;)可读性更好。
- 防止 XSS 攻击时,用户输入应转义为实体后再显示。
- 现代框架(React、Vue)默认会转义,但 dangerouslySetInnerHTML 和 v-html 需要手动处理。
- 转义顺序要一次到位,先把 & 换成 & 再处理其它字符,逐个替换会漏掉被转义结果里新产生的 &。
- 表示不换行空格,普通排版间隙用 CSS 的 gap 或 margin,不要拿实体当间距工具。
- 形如 © 与 © 在部分老解析器下表现不一致,输出规范数据时统一补分号。
常见问题
同一批 HTML 内容里,命名实体和数字实体应该怎么选?
按输出目标选,而不是按习惯选。写入 HTML 正文、给别人看源码、需要 diff 可读时用命名实体(&、©、→),语义直接写在名字里;写进 JSON、JS 字符串,或对接只认有限字符集的旧系统时用数字实体(&、©、→),它不依赖解析器是否认识某个名字。整页已经声明 UTF-8 时,©、→、α 这类符号直接写原字符最省事,实体只是兜底。
为什么转义时必须第一个处理和号 &?
因为 & 是实体的起始字符,必须一次性按固定顺序替换:先把所有 & 换成 &,再处理 < 和 >。如果逐个替换并且先动 <,那么一个已经变成 < 的字符串会被后面的规则再次命中,& 变 &amp;,页面里就会显示出字面量 < 而不是尖括号。对只做了一次转义的用户输入,重复转义同样会污染输出。
&nbsp; 能拿来当排版间距用吗?
不建议。它表示的是不间断空格( ),语义是「在这个位置不允许换行」,常用于人名、数字与单位之间、表格里不该被折断的短词。把它当 margin 或 gap 用会让排版规则散落在正文字符里,且屏幕阅读器会把多余的不间断空格读出来。纯视觉间隙交给 CSS 的 gap 或 margin,需要防止换行时才用 &nbsp;。
把命名实体写成不带分号的形式,比如 &copy 而不是 &copy;,会有什么风险?
风险不在现代解析器,而在混合来源。分号是实体结束的唯一可靠标记,HTML5 解析器对无分号形式有条件回退,但同一段文本一旦被正则、模板引擎、邮件客户端或老旧 XML 解析器二次处理,缺少分号就可能被当成普通字面文本吃掉或截断。规则很简单:输出机器可读的数据时统一补分号;只在人写的文档里偶尔省略,也要保证后面紧跟的字符不会把实体名续长(比如 &copycat 会被理解成 &copy 加 cat)。
& 与 &amp; 之外,为什么 &lt; 和 &gt; 的转义是强制项?
因为它们不是排版符号,而是 HTML 自身的语法字符。未转义的 < 会被解析器当作标签起始,后面的内容要么消失要么变成属性;未转义的 > 在部分上下文里会提前闭合标签。结果是页面结构变形,标签边界由数据决定——这正是把用户输入拼进 HTML 时最常见的 XSS 入口。&quot;(")与 &apos;(')是否必转则取决于所处位置:在属性值里双引号必须转义,单引号在双引号包裹的属性中可以原样保留。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。