要为额外的转义序列(\p{xx}、\P{xx} 和 \X)选择 UTF-8 模式,请使用“u”修饰符(参见 https://php.net/manual/en/reference.pcre.pattern.modifiers.php)。
我很好奇为什么德语的尖锐 S(ß)被 \p{Cc} 标记为控制字符,我花了一段时间才正确阅读第一句话:“从 5.1.0 开始,当选择 UTF-8 模式时,可以使用三种额外的转义序列来匹配通用字符类型。”:-$ 然后才发现如何做到这一点。从 5.1.0 开始,当选择 _UTF-8 模式_ 时,可以使用三种额外的转义序列来匹配通用字符类型。它们是
上面由 xx 表示的属性名称仅限于 Unicode 通用类别属性。每个字符都只有一个这样的属性,由一个两位字母的缩写指定。为了与 Perl 保持兼容,否定可以通过在开括号和属性名称之间包含一个插入符号来指定。例如,\p{^Lu} 与 \P{Lu} 相同。
如果只用 \p 或 \P 指定一个字母,它将包括以该字母开头的所有属性。在这种情况下,在没有否定的情况下,转义序列中的花括号是可选的;这两个示例具有相同的效果
\p{L}
\pL
| 属性 | 匹配 | 备注 | 
|---|---|---|
| C | 其他 | |
| Cc | 控制 | |
| Cf | 格式 | |
| Cn | 未分配 | |
| Co | 专用使用 | |
| Cs | 代理 | |
| L | 字母 | 包括以下属性: Ll、Lm、Lo、Lt和Lu。 | 
| Ll | 小写字母 | |
| Lm | 修饰字母 | |
| Lo | 其他字母 | |
| Lt | 标题大小写字母 | |
| Lu | 大写字母 | |
| M | 标记 | |
| Mc | 间隔标记 | |
| Me | 封闭标记 | |
| Mn | 非间隔标记 | |
| N | 数字 | |
| Nd | 十进制数字 | |
| Nl | 字母数字 | |
| No | 其他数字 | |
| P | 标点符号 | |
| Pc | 连接标点符号 | |
| Pd | 破折号标点符号 | |
| Pe | 结束标点符号 | |
| Pf | 最终标点符号 | |
| Pi | 初始标点符号 | |
| Po | 其他标点符号 | |
| Ps | 开始标点符号 | |
| S | 符号 | |
| Sc | 货币符号 | |
| Sk | 修饰符符号 | |
| Sm | 数学符号 | |
| So | 其他符号 | |
| Z | 分隔符 | |
| Zl | 换行符 | |
| Zp | 段落分隔符 | |
| Zs | 空格分隔符 | 
PCRE 不支持 InMusicalSymbols 等扩展属性。
指定不区分大小写(不区分大小写)匹配不会影响这些转义序列。例如,\p{Lu} 始终只匹配大写字母。
Unicode 字符集被定义为属于某些脚本。可以使用脚本名称匹配来自这些集合之一的字符。例如
\p{Greek}
   \P{Han}
   那些不属于已识别脚本的字符被归类为 Common。当前的脚本列表是
| 阿拉伯语 | 亚美尼亚语 | 阿维斯塔语 | 巴厘语 | 巴穆姆语 | |
| 巴塔克语 | 孟加拉语 | 注音符号 | 婆罗米语 | 盲文 | |
| 布吉语 | 布希德语 | 加拿大原住民 | 卡里亚语 | 恰克马语 | |
| 占语 | 切罗基语 | 通用 | 科普特语 | 楔形文字 | |
| 塞浦路斯语 | 西里尔语 | 德塞雷特语 | 天城体 | 埃及象形文字 | |
| 埃塞俄比亚语 | 格鲁吉亚语 | 格拉哥里字母 | 哥特语 | 希腊语 | |
| 古吉拉特语 | 旁遮普语 | 汉语 | 韩语 | 哈努诺语 | |
| 希伯来语 | 平假名 | 帝国亚兰语 | 继承 | 铭文帕拉维语 | |
| 铭文帕提亚语 | 爪哇语 | 凯西语 | 卡纳达语 | 片假名 | |
| 卡雅李语 | 佉卢文 | 高棉语 | 老挝语 | 拉丁语 | |
| 雷布查语 | 林布语 | 线形文字 B | 丽苏语 | 利西亚语 | |
| 利底亚语 | 马拉雅拉姆语 | 曼达语 | 梅泰马耶克语 | 梅罗埃草书 | |
| 梅罗埃象形文字 | 苗语 | 蒙古语 | 缅甸语 | 新泰卢语 | |
| 恩科语 | 奥甘文字 | 古意大利语 | 古波斯语 | 古代南阿拉伯语 | |
| 古代突厥语 | 奥尔奇基语 | 奥里亚语 | 奥斯曼尼亚语 | 八思巴文 | |
| 腓尼基语 | 雷丈语 | 卢恩字母 | 撒马利亚语 | 索拉什特拉语 | |
| 沙拉达语 | 萧氏字母 | 僧伽罗语 | 索拉索彭语 | 巽他语 | |
| 西洛提·纳格里语 | 叙利亚语 | 他加禄语 | 塔班瓦语 | 泰勒语 | |
| 泰喃语 | 泰越语 | 塔克里语 | 泰米尔语 | 泰卢固语 | |
| 塔纳语 | 泰语 | 藏语 | 提菲纳格字母 | 乌加里特语 | |
| 瓦伊语 | 彝语 | 
\X 转义匹配 Unicode 扩展字形集群。扩展字形集群是一个或多个 Unicode 字符,它们组合在一起形成单个字形。实际上,这可以被认为是 . 的 Unicode 等效项,因为它将匹配一个组合字符,而不管实际用于呈现它的单个字符数量。
在早于 8.32 版本的 PCRE(对应于使用捆绑的 PCRE 库的 PHP 版本早于 5.4.14 版本)中,\X 等效于 (?>\PM\pM*)。也就是说,它匹配一个没有“标记”属性的字符,后面跟着零个或多个具有“标记”属性的字符,并将该序列视为一个原子组(见下文)。具有“标记”属性的字符通常是影响前一个字符的重音符号。
通过 Unicode 属性匹配字符速度并不快,因为 PCRE 必须搜索包含超过一万五千个字符数据的结构。这就是为什么传统的转义序列(如 \d 和 \w)在 PCRE 中不使用 Unicode 属性的原因。
要为额外的转义序列(\p{xx}、\P{xx} 和 \X)选择 UTF-8 模式,请使用“u”修饰符(参见 https://php.net/manual/en/reference.pcre.pattern.modifiers.php)。
我很好奇为什么德语的尖锐 S(ß)被 \p{Cc} 标记为控制字符,我花了一段时间才正确阅读第一句话:“从 5.1.0 开始,当选择 UTF-8 模式时,可以使用三种额外的转义序列来匹配通用字符类型。”:-$ 然后才发现如何做到这一点。示例总是很有用!请参阅 https://unicodeplus.com/category 获取更多信息。
C 其他
Cc 控制(Unicode 代码点在范围 U+0000-U+001F 和 U+007F-U+009F 中)
Cf 格式(软连字符(U+00AD)、零宽度空格(U+200B)等)
Cn 未分配(Unicode 表中不存在的任何代码点)
Co 专用使用
Cs 代理(范围 U+D800 到 U+DFFF 中的字符,在 utf-8 中无效)
L 字母
Ll 小写字母(a-z、µßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ 等等)
Lm 修饰字母(类似字母的字符,通常与其他字符组合,但在这里它们独立存在
ʰʱʲʳʴʵʶʷʸʹʺʻʼʽʾʿˀˁˆˇˈˉˊˋˌˍˎˏːˑˠˡˢˣˤˬˮʹͺՙ 等等)
Lo 其他字母(ªºƻǀǁǂǃʔ 和更多来自 unicase 字母的象形文字和字母)
Lt 标题大小写字母(DžLjNjDzᾈᾉᾊᾋᾌᾍᾎᾏᾘᾙᾚᾛᾜᾝᾞᾟᾨᾩᾪᾫᾬᾭᾮᾯᾼῌῼ)
Lu 大写字母(A-Z、ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ 等等)
L& 普通字母(任何具有 Lu、Ll 或 Lt 属性的字符)
M 标记
Mc 间隔标记(拉丁字母中没有)
Me 封闭标记(组合封闭方块(U+20DE),如 a⃞ 中,组合封闭圆反斜杠(U+20E0),如 a⃠ 中)
Mn 非间隔标记(组合变音符号 U+0300-U+036f,例如此字母 a 上的重音符号:áâãāa̅ăȧäảåa̋ǎa̍a̎ȁa̐ȃ)
N 数字
Nd 十进制数字(0123456789、٠١٢٣٤٥٦٧٨٩ 和许多其他脚本中的数字。)
Nl 字母数字(ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫⅬⅭⅮⅯⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⅼⅽⅾⅿ 和更多一些)
No 其他数字(⁰¹²³⁴⁵⁶⁷⁸⁹ ₀₁₂₃₄₅₆₇₈₉ ½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⅒ ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ 等等)
P 标点符号
Pc 连接标点符号(下划线(U+005F)、‿ 下连字 (U+203F)、⁀ 字元连接符 (U+2040) 等)
Pd 破折号标点符号(- 连字符 (U+002D)、‐ 短破折号 (U+2010)、‑ 不间断连字符 (U+2011)、‒ 数字破折号 (U+2012)、
– 短破折号 (U+2013)、— 长破折号 (U+2014)、― 横线 (U+2015) 等)
Pe 关闭标点符号(右括号、方括号或大括号:`)` (U+0029)、`]` (U+005D)、`}` (U+007D) 等)
Pf 结尾标点符号(右引号:» (U+00BB)、’ (U+2019)、” (U+201D) 等)
Pi 开始标点符号(左引号:« (U+00AB)、‘ (U+2018)、“ (U+201C) 等)
Po 其他标点符号 (!"#%&'*,./:;?@\¡§¶·¿)
Ps 打开标点符号(左括号、方括号或大括号:`(` (U+0028)、`[` (U+005B)、`{` (U+007B) 等)
S 符号
Sc 货币符号 ($¢£¤¥, ₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ € ₭ ₮ ₯ ₰ ₱ ₲ ₳ ₴ ₵ ₶ ₷ ₸ ₹ ₺ ₻ ₼ ₽ ₾ ₿ (U+20A0-U+20BF) 等)
Sk 修饰符号(通常与其他符号组合使用的符号类字符,但此处它们单独存在
^`¨¯´¸ 等等)
Sm 数学符号 (+<=>|~¬±×÷϶ 等等)
So 其他符号 (¦ 断线 (U+00A6)、© 版权符号 (U+00A9)、® 注册商标符号 (U+00AE)、° 度数符号 (U+00B0);
箭头、符号、表情符号等等)
Z 分隔符
Zl 行分隔符(行分隔符 (U+2028))
Zp 段落分隔符(段落分隔符 (U+2029))
Zs 空格分隔符(空格、不间断空格、全角空格、半角空格、字间空格、词间空格、数字空格、细空格、极细空格等)我的国家,越南,有自己的字母表
http://en.wikipedia.org/wiki/Vietnamese_alphabet
我希望 PHP 在越南语方面能提供更好的支持。对于那些想知道的人:'letter_titlecase' 应用于二合字/三合字,其中大写仅涉及第一个字母。
例如,Unicode 中的 "LJ" 二合字有三个代码点
(*) 大写 "LJ": U+01C7
(*) 标题大小写 "Lj": U+01C8
(*) 小写 "lj": U+01C9页面顶部说明中没有明确说明,但这些转义字符类可以包含在方括号中,以构成更广泛的字符类。例如
<?php preg_match( '/[\p{N}\p{L}]+/', $data ) ?>
将匹配字母和数字的任何组合。这些属性通常只有在 PCRE 使用 "--enable-unicode-properties" 编译时才可用
如果你想匹配任何单词,但又想提供一个备用方案,你可以这样做
<?php 
if(@preg_match_all('/\p{L}+/u', $str, $arr) { 
 // 备用方案在这里 
 // 例如,对于不太精确的匹配,使用 '/\w+/u' 
} 
?>如果你使用的是旧环境,你需要先检查 PCRE 版本是否支持上述 Unicode 指令
<?php
// 需要检查 PCRE 版本,因为一些环境
// 运行的是旧版本的 PCRE 库
//(在 *nix 环境中运行 `pcretest -C`)
$allowInternational = false;
if (defined('PCRE_VERSION')) {
 if (intval(PCRE_VERSION) >= 7) { // 自 PHP 5.2.4 起可用常量
 $allowInternational = true;
 }
}
?>
现在,当 PCRE 库版本过旧或不可用时,你可以使用备用正则表达式(例如,使用 "/[a-z]/i")。对于那些想知道的人:'letter_titlecase' 应用于二合字/三合字,其中大写仅涉及第一个字母。
例如,Unicode 中的 "LJ" 二合字有三个代码点
(*) 大写 "LJ": U+01C7
(*) 标题大小写 "Lj": U+01C8
(*) 小写 "lj": U+01C9我发现预定义的 "supported" 脚本很有用,只是没有明确说明这些定义包含哪些 Unicode 字符范围。所以我写了这段代码来确定它们并打印出等效的 PCRE 字符类定义。输出片段示例如下(由于 PHP.net 帖子限制,我无法包含所有输出)
Canadian_Aboriginal=[\x{1400}-\x{167f}\x{18b0}-\x{18f5}]
程序
<?php
$scriptNames = array(
 '阿拉伯语',
 '亚美尼亚语',
 '阿维斯塔语',
 '巴厘语',
 '巴穆姆语',
 '巴塔克语',
 '孟加拉语',
 '注音符号',
 '婆罗米文',
 '盲文',
 '布吉语',
 '布希德语',
 '加拿大原住民语言',
 '卡里亚语',
 '恰克玛语',
 '占语',
 '切罗基语',
 '通用',
 '科普特语',
 '楔形文字',
 '塞浦路斯语',
 '西里尔字母',
 '德塞雷特字母',
 '天城体',
 '埃及象形文字',
 '埃塞俄比亚语',
 '格鲁吉亚语',
 '格拉哥里字母',
 '哥特语',
 '希腊语',
 '古吉拉特语',
 '旁遮普语',
 '汉语',
 '韩语',
 '哈努诺语',
 '希伯来语',
 '平假名',
 '帝国亚兰语',
 '继承',
 '铭文帕提亚语',
 '铭文帕尔提语',
 '爪哇语',
 '凯西语',
 '卡纳达语',
 '片假名',
 '克耶语',
 '佉卢文',
 '高棉语',
 '老挝语',
 '拉丁语',
 '列普查语',
 '林布语',
 '线性B文',
 '傈僳语',
 '利西亚语',
 '利底亚语',
 '马拉雅拉姆语',
 '曼达语',
 '麦泰语',
 '麦罗埃草书',
 '麦罗埃象形文字',
 '苗语',
 '蒙古语',
 '缅甸语',
 '新泰卢语',
 '恩科语',
 '奥甘文',
 '古意大利语',
 '古波斯语',
 '古南阿拉伯语',
 '古突厥语',
 '奥尔奇基语',
 '奥里亚语',
 '奥斯曼尼亚语',
 '八思巴文',
 '腓尼基语',
 '雷藏语',
 '卢恩字母',
 '撒玛利亚语',
 '索拉什特拉语',
 '沙拉达文',
 '肖文',
 '僧伽罗语',
 '索拉·索彭语',
 '巽他语',
 '西罗提·纳格里语',
 '叙利亚语',
 '他加禄语',
 '塔班瓦语',
 '泰语',
 '傣文',
 '傣维特语',
 '塔克里语',
 '泰米尔语',
 '泰卢固语',
 '塔纳语',
 '泰国语',
 '藏语',
 '提菲纳格字母',
 '乌加里特语',
 '瓦伊语',
 '彝语'
);
$scriptTypes = array();
foreach( $scriptNames as $n ) $scriptTypes[ $n ] = array();
for( $i=0; $i <= 0x10fff; $i++ ) {
//echo $i.PHP_EOL;
 foreach( $scriptNames as $scriptName ) {
 if ( preg_match( '/[\p{'. $scriptName .'}]/u', mb_chr( $i, 'UTF-8') ) ) {
 if (empty( $scriptTypes[ $scriptName ])
 || ( ($i - $scriptTypes[ $scriptName ][ count( $scriptTypes[ $scriptName ] ) - 1 ][1]) > 1)
 ) {
 $scriptTypes[ $scriptName ][] = [$i, $i];
 } else {
 $scriptTypes[ $scriptName ][ count( $scriptTypes[ $scriptName ] ) - 1 ][1] = $i;
 }
 }
 }
}
foreach( $scriptTypes as $scriptName => $unicodeRanges ) {
 printf(
 '%s=[',
 $scriptName
 );
 foreach( $unicodeRanges as $r ) {
 printf(
 '\x{%04x}',
 $r[0]
 );
 if ($r[1] > $r[0] )
 printf(
 '-\x{%04x}',
 $r[1]
 );
 }
 printf(
 ']'.PHP_EOL
 );
}