Unicode 转义序列
在源代码中表示Unicode字符的语法,各语言不同:\u2713(Python/Java/JS)、\u{2713}(JS/Ruby/Rust)、\U00012345(Python/C)。
What Are Unicode Escape Sequences?
Unicode escape sequences are a notation for representing Unicode characters in source code using only ASCII characters. Instead of embedding the actual character (which may not be typeable or visible), you write a backslash-based sequence that the language parser converts to the character at compile or parse time.
The exact syntax varies by language, but two forms dominate:
\uXXXX: Four hex digits — covers the Basic Multilingual Plane (U+0000–U+FFFF).\UXXXXXXXX: Eight hex digits — covers all Unicode including supplementary planes (U+0000–U+10FFFF).
Language-by-Language Syntax
# Python
"\u00A9" # © (U+00A9, 4-digit BMP)
"\U0001F600" # 😀 (U+1F600, 8-digit supplementary)
"\N{SNOWMAN}" # ☃ (named character)
"\x00A9" # © (also valid: 2-digit hex byte)
# All identical:
"\u00A9" == "\U000000A9" == "©" # True
// JavaScript
"\u00A9" // © (BMP)
"\u{1F600}" // 😀 (ES6+ brace notation, any code point)
"\uD83D\uDE00" // 😀 (legacy: surrogate pair for supplementary)
// ES6 brace notation is recommended:
"\u{1F1FA}\u{1F1F8}" // 🇺🇸 (flag sequence)
// Java — only \uXXXX (BMP), surrogates needed for supplementary
"\u00A9" // ©
"\uD83D\uDE00" // 😀 (surrogate pair)
// Java has no \U syntax — use char literals or Character.toChars()
// C#
"\u00A9" // ©
"\U0001F600" // 😀
"\x00A9" // ©
// Rust
"\u{A9}" // © (brace notation, variable length)
"\u{1F600}" // 😀
// Go
"\u00A9" // © (rune literal, BMP)
"\U0001F600" // 😀 (rune literal, supplementary)
Java's Unusual Preprocessing
Java processes \uXXXX escapes during lexical preprocessing — before the tokenizer runs. This means a Unicode escape can appear in virtually any context including comments and string literals:
// The following comment contains a \u000A which is a newline!
// This will compile and affect the next line
int x = 1; // \u000A x = 2;
// Effectively parsed as:
// int x = 1;
// x = 2;
This is a subtle Java gotcha: Unicode escapes in comments can inject real source code.
Using Escapes in Practice
# When to use escapes:
# 1. In code that must be ASCII-safe
ARROW = "\u2192" # → RIGHT ARROW
# 2. For control characters
NULL = "\u0000" # NUL
LINE_SEP = "\u2028" # LINE SEPARATOR
# 3. For documentation clarity
ZWJ = "\u200D" # Zero Width Joiner — invisible in source
NBSP = "\u00A0" # Non-Breaking Space — invisible in source
# Named escapes (Python only) — most readable
import unicodedata
"\N{COPYRIGHT SIGN}" # ©
"\N{ZERO WIDTH JOINER}" # (ZWJ)
// ES6+ template literals with escapes
const message = `Copyright \u{A9} 2024 \u{2014} All rights reserved`;
// "Copyright © 2024 — All rights reserved"
Escape vs. Direct Character
In UTF-8 source files, direct characters are generally preferred for readability:
# Readable — direct character
emoji = "😀"
# ASCII-safe — escape (useful in legacy systems)
emoji = "\U0001F600"
# Both produce identical runtime values
"😀" == "\U0001F600" # True
Quick Facts
| Language | BMP syntax | Full range syntax |
|---|---|---|
| Python | \uXXXX |
\UXXXXXXXX or \N{name} |
| JavaScript | \uXXXX |
\u{XXXXX} (ES6+) |
| Java | \uXXXX |
Surrogate pairs only |
| C# | \uXXXX |
\UXXXXXXXX |
| Rust | \u{X} to \u{XXXXXX} |
Same (variable length) |
| Go | \uXXXX |
\UXXXXXXXX |
| CSS | \XXXXXX |
Same (1–6 hex digits) |
编程与开发 中的更多内容
Java strings use UTF-16 internally. char is 16-bit (only BMP). For supplementary …
Python 3 uses Unicode strings by default (str = UTF-8 internally via …
Rust strings (str/String) are guaranteed valid UTF-8. char type represents a Unicode …
使用Unicode属性的正则表达式模式:\p{L}(任意字母)、\p{Script=Greek}(希腊文字)、\p{Emoji},各语言和正则引擎的支持程度不同。
无可见字形的字符:空白、零宽字符、控制字符和格式字符,可能引发欺骗和文本隐写等安全问题。
用错误编码解码字节时产生的乱码文本,来自日语词“文字化け”。例如:'café'以UTF-8存储但用Latin-1读取,显示为'café'。
在UTF-16中一起编码补充字符的两个16位码元(高代理U+D800–U+DBFF + 低代理U+DC00–U+DFFF),😀 = D83D DE00。
编程语言中的字符序列,内部表示各异:UTF-8(Go、Rust、新版Python)、UTF-16(Java、JavaScript、C#)或UTF-32(Python)。
Unicode字符串的“长度”取决于计量单位:码元(JavaScript .length)、码位(Python len())或字素簇。👨👩👧👦 = 7个码位,1个字素。
U+FFFD(�),解码器遇到无效字节序列时显示的字符——“解码出错”的通用符号。