Unicode_Code_Point

 encode
 

Unicode字符多种多样,除去ascii中的字母、数字、标点和中文字符,还包括其它多种语言和多种符号,有些符号甚至很难打出来(比如表示商标注册的字符),这时候该如何表示呢?再说远一点,如果我们想用一个字符组匹配所有中文字符,能不能像『[a-z]』那样呢?

所幸,每一个Unicode字符都对应自己的Unicode编码,也就是Unicode编码表中的一个代码点(Code Point),所以在正则表达式中的Unicode字符往往采用Unicode代码点来指定。

一般来说,指定代码点的形式有3种:『\uxxxx』、『\u{xxxx}』、『\x{xxxx}』(其中的xxxx为编码的值,\u之后必须有4位16进制数字)。.NET、Java、JavaScript和Python使用第一种方式,而PHP和Ruby使用第二种方式(Ruby 1.9以上版本才支持这种表示法),PHP使用第三种方式。

比如“发表”的“发”字对应的Unicode编码是53 d1,它在不同语言中的表示法如下:所以我们可以在.NET、Java、JavaScript的正则表达式中这样表示“发”字:“\u53d1”,Python稍有不同,必须使用u”\u53d1”(之前的u表示这是一个Unicode字符串); Ruby中,“发”则必须写作”\u{53d1}”。

编码 语言 表示方法 备注
53 d1 .NET \u53d1
53 d1 Java \u53d1
53 d1 JavaScript \u53d1
53 d1 Python \u53d1 必须使用Unicode字符串,Python 2.x中,要在字符串之前加u
53 d1 Ruby \u{53d1} 限Ruby 1.9以上版本,且必须显式指定Unicode模式
53 d1 PHP \x{53d1} 必须指定Unicode模式

既然可以这样指定Unicode字符,自然也可以在字符组中用范围表示法指定一个Unicode编码范围了。比如,我们查询Unicode编码表可知,中文的编码一般在4e00到9fff之间,所以可以用这样的字符组匹配中文字符(Unicode编码4e00-9fff归类为“CJK 统一表意符号”CJK Unified Ideographs,涵盖了绝大多数中文字符):

语言 字符组 备注
.NET [\u4e00-\u9fff]
Java [\u4e00-\u9fff]
JavaScript [\u4e00-\u9fff]
Python [\u4e00-\u9fff] 必须使用Unicode字符串,Python 2.x中,要在字符串之前加u
Ruby [\x{4e00}-\x{9fff}] 限Ruby 1.9以上版本,且必须显式指定Unicode模式
PHP [\u{4e00}-\u{9fff}] 必须指定Unicode模式

根据Unicode规范,每一个Unicode字符除了有唯一代码点对应,还具有其它属性,现在详细介绍三种属性,它们是:Unicode Property、Unicode Block、Unicode Script,下面的图粗略说明了这三者的关系。
img

Unicode Property

Unicode Property的记法类似『\p{L}』、『\p{Lo}』,它按照字符的功能分类Unicode字符,而不关心字符属于哪种语言,每个Unicode字符只能属于唯一Unicode Property。

举例来说,『\p{Z}』表示任意的空白字符或不可见的分隔符;『\p{P}』表示任何标点字符,等等。遇到中英文混排、全角半角同时出现的情况,我们就可以用『\p{Z}』匹配所有的空白字符(而不用关心空格到底是全角空格还是半角空格),用『\p{P}』匹配所有的标点字符(而不用关心逗号到底是中文逗号还是英文逗号),而不用费心细节。

如果我们把Unicode Property理解为一个“字符组”,那么它一定能对应某个排除型字符组,此排除型字符组的通行记法是将『\p{xx}』中的小写p改为大写P,写作『\P{xx}』。这样,『\P{Z}』对应『\p{Z}』无法匹配的字符,『\p{P}』对应『\p{P}』无法匹配的字符。Unicode Block和Unicode Script对应的排除型字符组也是这样标记,下面不再赘述。

支持Unicode Property的语言有.NET、Java、PHP和Ruby(限1.9以上版本),在PHP和Ruby中使用Unicode Property时,必须要开启Unicode模式,下面以『\p{P}』的匹配为例:

.NET

1
Regex.IsMatch(',', "\\p{P}"); //true

Java

1
",".matches("\\p{P}"); //true

PHP

1
preg_match('/\p{P}/u', ','); //1

Ruby 1.9

1
'/\p{P}/u' =~ ',' # 0

Python需要安装扩展库regex来实现:

1
pip install regex

1
match = regex.match("\\p{P}", ",") #<regex.Match object; span=(0, 1), match=','>

下图为所有的Unicode Property,单字母表示所有以此字母开头的所有属性,例如Z包含了Zs、Zl、Zp:
img

Unicode Block

Unicode Block则不同于Unicode Property,它按照编码区间划分Unicode字符,每个Unicode Block中的字符编码都是落在同一个连续区间的。因为Unicode编码表中,某种语言的字符通常是落在同一区间的,所以它也可以粗略表示某类语言的字符,比如\p{InHebrew}表示希伯莱语字符,『\p{InCJK_Compatibility}』表示兼容CJK(汉语、韩语、日本语)的字符。如果你细心观察,会发现Unicod Block的名字虽然类似某种语言的名字,但都有“In”(Java风格)或者“Is”(.NET风格)前缀,这表明它其实对应的还是“落在某个区间的Unicode字符”。

只有Java和.NET支持Unicode Block,它们的写法不相同:

Java

1
"我".matches("\\p{InCJK_Compatibility_Ideographs}"); //true

.NET

1
Regex.IsMatch('我', "\\p{IsCJK_Compatibility_Ideographs}"); //true

下图为完整的Unicode Block:

  • \p{InBasic_Latin}: U+0000–U+007F
  • \p{InLatin-1_Supplement}: U+0080–U+00FF
  • \p{InLatin_Extended-A}: U+0100–U+017F
  • \p{InLatin_Extended-B}: U+0180–U+024F
  • \p{InIPA_Extensions}: U+0250–U+02AF
  • \p{InSpacing_Modifier_Letters}: U+02B0–U+02FF
  • \p{InCombining_Diacritical_Marks}: U+0300–U+036F
  • \p{InGreek_and_Coptic}: U+0370–U+03FF
  • \p{InCyrillic}: U+0400–U+04FF
  • \p{InCyrillic_Supplementary}: U+0500–U+052F
  • \p{InArmenian}: U+0530–U+058F
  • \p{InHebrew}: U+0590–U+05FF
  • \p{InArabic}: U+0600–U+06FF
  • \p{InSyriac}: U+0700–U+074F
  • \p{InThaana}: U+0780–U+07BF
  • \p{InDevanagari}: U+0900–U+097F
  • \p{InBengali}: U+0980–U+09FF
  • \p{InGurmukhi}: U+0A00–U+0A7F
  • \p{InGujarati}: U+0A80–U+0AFF
  • \p{InOriya}: U+0B00–U+0B7F
  • \p{InTamil}: U+0B80–U+0BFF
  • \p{InTelugu}: U+0C00–U+0C7F
  • \p{InKannada}: U+0C80–U+0CFF
  • \p{InMalayalam}: U+0D00–U+0D7F
  • \p{InSinhala}: U+0D80–U+0DFF
  • \p{InThai}: U+0E00–U+0E7F
  • \p{InLao}: U+0E80–U+0EFF
  • \p{InTibetan}: U+0F00–U+0FFF
  • \p{InMyanmar}: U+1000–U+109F
  • \p{InGeorgian}: U+10A0–U+10FF
  • \p{InHangul_Jamo}: U+1100–U+11FF
  • \p{InEthiopic}: U+1200–U+137F
  • \p{InCherokee}: U+13A0–U+13FF
  • \p{InUnified_Canadian_Aboriginal_Syllabics}: U+1400–U+167F
  • \p{InOgham}: U+1680–U+169F
  • \p{InRunic}: U+16A0–U+16FF
  • \p{InTagalog}: U+1700–U+171F
  • \p{InHanunoo}: U+1720–U+173F
  • \p{InBuhid}: U+1740–U+175F
  • \p{InTagbanwa}: U+1760–U+177F
  • \p{InKhmer}: U+1780–U+17FF
  • \p{InMongolian}: U+1800–U+18AF
  • \p{InLimbu}: U+1900–U+194F
  • \p{InTai_Le}: U+1950–U+197F
  • \p{InKhmer_Symbols}: U+19E0–U+19FF
  • \p{InPhonetic_Extensions}: U+1D00–U+1D7F
  • \p{InLatin_Extended_Additional}: U+1E00–U+1EFF
  • \p{InGreek_Extended}: U+1F00–U+1FFF
  • \p{InGeneral_Punctuation}: U+2000–U+206F
  • \p{InSuperscripts_and_Subscripts}: U+2070–U+209F
  • \p{InCurrency_Symbols}: U+20A0–U+20CF
  • \p{InCombining_Diacritical_Marks_for_Symbols}: U+20D0–U+20FF
  • \p{InLetterlike_Symbols}: U+2100–U+214F
  • \p{InNumber_Forms}: U+2150–U+218F
  • \p{InArrows}: U+2190–U+21FF
  • \p{InMathematical_Operators}: U+2200–U+22FF
  • \p{InMiscellaneous_Technical}: U+2300–U+23FF
  • \p{InControl_Pictures}: U+2400–U+243F
  • \p{InOptical_Character_Recognition}: U+2440–U+245F
  • \p{InEnclosed_Alphanumerics}: U+2460–U+24FF
  • \p{InBox_Drawing}: U+2500–U+257F
  • \p{InBlock_Elements}: U+2580–U+259F
  • \p{InGeometric_Shapes}: U+25A0–U+25FF
  • \p{InMiscellaneous_Symbols}: U+2600–U+26FF
  • \p{InDingbats}: U+2700–U+27BF
  • \p{InMiscellaneous_Mathematical_Symbols-A}: U+27C0–U+27EF
  • \p{InSupplemental_Arrows-A}: U+27F0–U+27FF
  • \p{InBraille_Patterns}: U+2800–U+28FF
  • \p{InSupplemental_Arrows-B}: U+2900–U+297F
  • \p{InMiscellaneous_Mathematical_Symbols-B}: U+2980–U+29FF
  • \p{InSupplemental_Mathematical_Operators}: U+2A00–U+2AFF
  • \p{InMiscellaneous_Symbols_and_Arrows}: U+2B00–U+2BFF
  • \p{InCJK_Radicals_Supplement}: U+2E80–U+2EFF
  • \p{InKangxi_Radicals}: U+2F00–U+2FDF
  • \p{InIdeographic_Description_Characters}: U+2FF0–U+2FFF
  • \p{InCJK_Symbols_and_Punctuation}: U+3000–U+303F
  • \p{InHiragana}: U+3040–U+309F
  • \p{InKatakana}: U+30A0–U+30FF
  • \p{InBopomofo}: U+3100–U+312F
  • \p{InHangul_Compatibility_Jamo}: U+3130–U+318F
  • \p{InKanbun}: U+3190–U+319F
  • \p{InBopomofo_Extended}: U+31A0–U+31BF
  • \p{InKatakana_Phonetic_Extensions}: U+31F0–U+31FF
  • \p{InEnclosed_CJK_Letters_and_Months}: U+3200–U+32FF
  • \p{InCJK_Compatibility}: U+3300–U+33FF
  • \p{InCJK_Unified_Ideographs_Extension_A}: U+3400–U+4DBF
  • \p{InYijing_Hexagram_Symbols}: U+4DC0–U+4DFF
  • \p{InCJK_Unified_Ideographs}: U+4E00–U+9FFF
  • \p{InYi_Syllables}: U+A000–U+A48F
  • \p{InYi_Radicals}: U+A490–U+A4CF
  • \p{InHangul_Syllables}: U+AC00–U+D7AF
  • \p{InHigh_Surrogates}: U+D800–U+DB7F
  • \p{InHigh_Private_Use_Surrogates}: U+DB80–U+DBFF
  • \p{InLow_Surrogates}: U+DC00–U+DFFF
  • \p{InPrivate_Use_Area}: U+E000–U+F8FF
  • \p{InCJK_Compatibility_Ideographs}: U+F900–U+FAFF
  • \p{InAlphabetic_Presentation_Forms}: U+FB00–U+FB4F
  • \p{InArabic_Presentation_Forms-A}: U+FB50–U+FDFF
  • \p{InVariation_Selectors}: U+FE00–U+FE0F
  • \p{InCombining_Half_Marks}: U+FE20–U+FE2F
  • \p{InCJK_Compatibility_Forms}: U+FE30–U+FE4F
  • \p{InSmall_Form_Variants}: U+FE50–U+FE6F
  • \p{InArabic_Presentation_Forms-B}: U+FE70–U+FEFF
  • \p{InHalfwidth_and_Fullwidth_Forms}: U+FF00–U+FFEF
  • \p{InSpecials}: U+FFF0–U+FFFF

Unicode Script

Unicode Script按照字符所属的书写系统来划分Unicode字符,比如\p{Greek}表示希腊语字符,\p{Han}表示汉语(中文字符)。它的写法类似Unicode Block,只是名字的开头没有“Is”或者“In”。

只有PHP和Ruby(限1.9以上版本)支持Unicode Script,PHP在使用Unicode Script时,必须开启Unicode模式(详见xx页)。在这两种语言中,我们可以很方便地用\p{Han}来匹配中文字符。

PHP

1
preg_match('/\p{Han}/u', '我'); //1

Ruby 1.9

1
/\p{Han}/u =~ '我' #0

下面为完整的Unicode Script

  • \p{Common}
  • \p{Arabic}
  • \p{Armenian}
  • \p{Bengali}
  • \p{Bopomofo}
  • \p{Braille}
  • \p{Buhid}
  • \p{Canadian_Aboriginal}
  • \p{Cherokee}
  • \p{Cyrillic}
  • \p{Devanagari}
  • \p{Ethiopic}
  • \p{Georgian}
  • \p{Greek}
  • \p{Gujarati}
  • \p{Gurmukhi}
  • \p{Han}
  • \p{Hangul}
  • \p{Hanunoo}
  • \p{Hebrew}
  • \p{Hiragana}
  • \p{Inherited}
  • \p{Kannada}
  • \p{Katakana}
  • \p{Khmer}
  • \p{Lao}
  • \p{Latin}
  • \p{Limbu}
  • \p{Malayalam}
  • \p{Mongolian}
  • \p{Myanmar}
  • \p{Ogham}
  • \p{Oriya}
  • \p{Runic}
  • \p{Sinhala}
  • \p{Syriac}
  • \p{Tagalog}
  • \p{Tagbanwa}
  • \p{TaiLe}
  • \p{Tamil}
  • \p{Telugu}
  • \p{Thaana}
  • \p{Thai}
  • \p{Tibetan}
  • \p{Yi}