Unicode 字符属性

从 5.1.0 开始,当选择 _UTF-8 模式_ 时,可以使用三种额外的转义序列来匹配通用字符类型。它们是

\p{xx}
具有 xx 属性的字符
\P{xx}
没有 xx 属性的字符
\X
扩展 Unicode 序列

上面由 xx 表示的属性名称仅限于 Unicode 通用类别属性。每个字符都只有一个这样的属性,由一个两位字母的缩写指定。为了与 Perl 保持兼容,否定可以通过在开括号和属性名称之间包含一个插入符号来指定。例如,\p{^Lu}\P{Lu} 相同。

如果只用 \p\P 指定一个字母,它将包括以该字母开头的所有属性。在这种情况下,在没有否定的情况下,转义序列中的花括号是可选的;这两个示例具有相同的效果

\p{L}
\pL
支持的属性代码
属性 匹配 备注
C 其他  
Cc 控制  
Cf 格式  
Cn 未分配  
Co 专用使用  
Cs 代理  
L 字母 包括以下属性:LlLmLoLtLu
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 属性的原因。

添加注释

用户贡献的注释 10 个注释

19
huhwatnouDONTspamPLEASE at hotmail dot com
8 年前
要为额外的转义序列(\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 模式时,可以使用三种额外的转义序列来匹配通用字符类型。”:-$ 然后才发现如何做到这一点。
13
mercury at caucasus dot net
14 年前
可以在此处找到一篇解释所有这些属性的优秀文章:https://regexper.cn/unicode.html
3
Steve
1 年前
示例总是很有用!请参阅 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 空格分隔符(空格、不间断空格、全角空格、半角空格、字间空格、词间空格、数字空格、细空格、极细空格等)
10
xuantoaiph at gmail dot com
10 年前
我的国家,越南,有自己的字母表
http://en.wikipedia.org/wiki/Vietnamese_alphabet
我希望 PHP 在越南语方面能提供更好的支持。
4
o_shes01 at uni-muenster dot de
13 年前
对于那些想知道的人:'letter_titlecase' 应用于二合字/三合字,其中大写仅涉及第一个字母。
例如,Unicode 中的 "LJ" 二合字有三个代码点
(*) 大写 "LJ": U+01C7
(*) 标题大小写 "Lj": U+01C8
(*) 小写 "lj": U+01C9
2
php at lnx-bsp dot net
6 年前
页面顶部说明中没有明确说明,但这些转义字符类可以包含在方括号中,以构成更广泛的字符类。例如

<?php preg_match( '/[\p{N}\p{L}]+/', $data ) ?>

将匹配字母和数字的任何组合。
3
suit at rebell dot at
14 年前
这些属性通常只有在 PCRE 使用 "--enable-unicode-properties" 编译时才可用

如果你想匹配任何单词,但又想提供一个备用方案,你可以这样做

<?php
if(@preg_match_all('/\p{L}+/u', $str, $arr) {
// 备用方案在这里
// 例如,对于不太精确的匹配,使用 '/\w+/u'
}
?>
1
Yzmir Ramirez
10 年前
如果你使用的是旧环境,你需要先检查 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")。
-4
o_shes01 at uni-muenster dot de
13 年前
对于那些想知道的人:'letter_titlecase' 应用于二合字/三合字,其中大写仅涉及第一个字母。
例如,Unicode 中的 "LJ" 二合字有三个代码点
(*) 大写 "LJ": U+01C7
(*) 标题大小写 "Lj": U+01C8
(*) 小写 "lj": U+01C9
-2
phpnet at N_O_S_P_A_M dot osps dot net
1 年前
我发现预定义的 "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
);
}
To Top