首页/开发/正则与编码速查/Unicode 大小写映射的复杂性

Unicode 大小写映射的复杂性

Unicode 大小写映射比 ASCII 复杂:存在一映射多(一个字符变大写后长度改变)、上下文相关(希腊语词尾 sigma)、语言相关(土耳其语 i)以及大小写折叠(casefold)这套专门用于比较的规则。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌​‌‌‌​​‌‌​‌​​‌​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌‌​​‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​​​​​‌‌‌​​​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

三类映射表

Unicode 用三套数据描述大小写:简单映射(每个码点对应一个码点,多数情况)、特殊映射(可能一对多,且部分规则依赖语言,例如德语小写字母变大写后变成两个字母、希腊语词尾 sigma 依上下文选择形态)、大小写折叠(专为「忽略大小写比较」设计,把字符折叠成可比较形式)。因此「转成大写」与「忽略大小写比较」是两件事:前者改变内容用于展示或规范,后者应使用折叠规则。此外不少字符没有大小写概念,汉字、数字、符号都属此类。

基本信息

简单映射一码点对一码点,覆盖大多数拉丁与希腊、西里尔字符
特殊映射存在一对多与语言相关规则(长度可能改变)
大小写折叠用于忽略大小写比较的专门映射,常与 lower 结果不同
语言敏感土耳其语与阿塞拜疆语的 i/I 映射与其他语言不同
上下文敏感希腊语 sigma 的词尾形态由位置决定
无大小写字符汉字、数字、符号等类别不参与大小写转换

典型使用场景

  • 用户名与邮箱比对:不敏感比较应使用折叠规则而非简单小写
  • 搜索与索引:查询词与索引内容统一折叠形式,保证召回一致
  • 数据规范化:对外展示统一大小写形态,注意长度可能改变
  • 标识符校验:转换后可能与既有数据冲突,需要唯一性策略
  • 国际化界面:不同语言环境的大小写习惯不同,避免硬编码规则

映射行为示例

映射行为示例
python -c "print('ß'.upper(), 'ß'.casefold(), len('ß'.upper()))"        # SS ss 2:一对多映射
python -c "print('Straße'.casefold() == 'STRASSE'.casefold())"          # True:折叠用于不敏感比较
python -c "print('İ'.lower(), 'i'.upper())"                              # 土耳其语相关的差异案例
python -c "print('中文ABC'.upper(), '中文ABC'.casefold())"               # 汉字不参与映射
python -c "print('hello world'.title(), \"don't\".title())"             # title 会把撇号后的字母也大写
# 不敏感比较的正确写法:casefold 两侧后再比较

操作与语义

操作用途注意点
upper转大写,用于展示或规范可能改变长度(一对多映射)
lower转小写,用于展示或规范与折叠结果不等价
casefold为不敏感比较做折叠比较应使用它而不是 lower
title / capitalize词首大写对缩写、撇号与连字符的处理常与预期不符
locale 敏感转换按语言规则转换需显式指定语言,默认值依实现而不同
长度会变:「一个字符变大写还是一个字符」在 Unicode 下不成立。凡是先转换再按位置索引、截断或截取子串的逻辑,都要考虑转换前后长度不同带来的错位。
语言相关的映射容易造成跨端不一致:某些语言环境下字母 i 的大小写规则与其他语言不同,同一份代码在不同服务器或用户语言下产出不同结果。涉及标识符时应显式指定语言或使用不敏感折叠而非语言相关转换。
「忽略大小写比较」还可能与归一化和视觉相似字符叠加:安全敏感场景需要先归一化、再折叠、再校验,并配合字符白名单,不能只做一次小写转换就认为等价。

易错点

  • 用 lower 做不敏感比较:部分字符的小写与折叠结果不同,比较结果出错 → 使用折叠规则
  • 假设转换不改变长度:一对多映射让长度变化,按位置截取出现错位 → 转换后重新计算位置
  • 依赖默认语言环境:同一输入在不同环境得到不同结果 → 显式指定语言或不使用语言相关转换
  • 用 title 处理人名与缩写:撇号、连字符后的字母被错误大写 → 按业务规则处理,必要时维护例外表
  • 对无大小写字符做转换后比较:汉字与符号结果不变,误以为校验生效 → 结合归一化与白名单

数据来源与参考

  • Unicode 官方:Case Mapping 与 SpecialCasing 数据说明
  • Unicode 官方:Case Folding(用于不敏感比较的映射)
  • Unicode 官方:Default Case Algorithms(UAX #44 相关章节)

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/unicode-case-mapping.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌​‌‌‌​​‌‌​‌​​‌​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌‌​​‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​​​​​‌‌‌​​​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​