PHP Conference Japan 2024

字符类

一个左方括号引入一个字符类,由一个右方括号终止。单独的右方括号没有特殊含义。如果需要将右方括号作为类的一个成员,则它应该作为类中的第一个数据字符(在初始插入符号之后,如果存在),或者用反斜杠转义。

一个字符类匹配主题中的单个字符;该字符必须在类定义的字符集中,除非类中的第一个字符是插入符号,在这种情况下,主题字符不能在类定义的字符集中。如果实际上需要插入符号作为类的一个成员,请确保它不是第一个字符,或者用反斜杠转义它。

例如,字符类 [aeiou] 匹配任何小写元音,而 [^aeiou] 匹配任何不是小写元音的字符。请注意,插入符号只是用于指定通过枚举不存在的字符来指定类中存在的字符的一种方便的表示法。它不是一个断言:它仍然从主题字符串中消耗一个字符,如果当前指针位于字符串的末尾,则失败。

当设置不区分大小写(不区分大小写)匹配时,类中的任何字母都表示其大写和小写版本,因此例如,不区分大小写的 [aeiou] 匹配 "A" 和 "a",而不区分大小写的 [^aeiou] 不匹配 "A",而区分大小写(区分大小写)版本则会匹配。

换行符在字符类中永远不会以任何特殊方式处理,无论 PCRE_DOTALLPCRE_MULTILINE 选项的设置如何。例如 [^a] 这样的类将始终匹配换行符。

减号 (-) 字符可用于指定字符类中的字符范围。例如,[d-m] 匹配 d 到 m 之间的任何字母,包括 d 和 m。如果类中需要减号字符,则必须用反斜杠转义它,或者出现在不能将其解释为表示范围的位置,通常是类中的第一个或最后一个字符。

无法将字面字符 "]" 作为范围的结束字符。例如 [W-]46] 的模式被解释为两个字符 ("W" 和 "-") 的类,后跟一个字面字符串 "46]",因此它将匹配 "W46]" 或 "-46]"。但是,如果 "]" 用反斜杠转义,则它被解释为范围的结束,因此 [W-\]46] 被解释为包含范围和两个单独字符的单个类。还可以使用 "]" 的八进制或十六进制表示形式来结束范围。

范围在 ASCII 排序顺序中运行。它们也可用于以数字指定的字符,例如 [\000-\037]。如果在设置不区分大小写(不区分大小写)匹配时使用包含字母的范围,则它将匹配这两种情况下的字母。例如,[W-c] 等效于 [][\^_`wxyzabc],不区分大小写匹配,如果正在使用“fr”语言环境的字符表,则 [\xc8-\xcb] 将匹配两种情况下的重音 E 字符。

字符类型 \d、\D、\s、\S、\w 和 \W 也可能出现在字符类中,并将它们匹配的字符添加到类中。例如,[\dABCDEF] 匹配任何十六进制数字。可以方便地将插入符号与大写字符类型一起使用,以指定比匹配的小写类型更受限制的字符集。例如,类 [^\W_] 匹配任何字母或数字,但不包括下划线。

除了 \, -、^(在开头)和终止的 ] 之外的所有非字母数字字符在字符类中都不是特殊的,但是如果它们被转义也不会造成任何损害。模式终止符始终是特殊的,并且在表达式中使用时必须转义。

Perl 支持 POSIX 字符类的表示法。这使用包含在包围方括号内的 [::] 中的名称。PCRE 也支持此表示法。例如,[01[:alpha:]%] 匹配 "0"、"1"、任何字母字符或 "%"。支持的类名称为

字符类
alnum字母和数字
alpha字母
ascii字符代码 0 - 127
blank仅空格或制表符
cntrl控制字符
digit十进制数字(与 \d 相同)
graph打印字符,不包括空格
lower小写字母
print打印字符,包括空格
punct打印字符,不包括字母和数字
space空白字符(与 \s 不完全相同)
upper大写字母
word“单词”字符(与 \w 相同)
xdigit十六进制数字
空格字符是 HT (9)、LF (10)、VT (11)、FF (12)、CR (13) 和空格 (32)。请注意,此列表包含 VT 字符(代码 11)。这使得“空格”与 \s 不同,后者不包含 VT(为了与 Perl 兼容)。

名称 word 是 Perl 扩展,blank 是 Perl 5.8 中的 GNU 扩展。另一个 Perl 扩展是否定,它由冒号后的 ^ 字符表示。例如,[12[:^digit:]] 匹配 "1"、"2" 或任何非数字。

在 UTF-8 模式下,值大于 128 的字符与任何 POSIX 字符类都不匹配。从 libpcre 8.10 开始,一些字符类已更改为使用 Unicode 字符属性,在这种情况下,上述限制不适用。有关详细信息,请参阅 » PCRE(3) 手册

Unicode 字符属性可以出现在字符类内部。它们不能是范围的一部分。Unicode 字符类之后的减号 (-) 字符将按字面意思匹配。尝试以 Unicode 字符属性结束范围将导致警告。

添加注释

用户贡献的注释 3 条注释

greaties at ghvernuft dot nl
3 年前
来自 http://www.pcre.org/pcre.txt 中的 PCRE 手册深处

\d 任何十进制数字
\D 任何不是十进制数字的字符
\h 任何水平空白字符
\H 任何不是水平空白字符的字符
\s 任何空白字符
\S 任何不是空白字符的字符
\v 任何垂直空白字符
\V 任何不是垂直空白字符的字符
\w 任何“单词”字符
\W 任何“非单词”字符
Julian
1 年前
字符类的示例

<?php

$stringA
= "1 起初 神创造天地。";
$stringB = preg_replace('/[[:^alnum:]]/', '', $stringA); // string(46) "1InthebeginningGodcreatedtheheavensandtheearth"
$stringC = preg_replace('/[[:^alpha:]]/', '', $stringA); // string(45) "InthebeginningGodcreatedtheheavensandtheearth"
$stringD = preg_replace('/[[:^ascii:]]/', '', "Pokémon"); // string(6) "Pokmon"
$stringE = preg_replace('/[[:^blank:]]/', '*', $stringA); // string(57) "* ** *** ********* *** ******* *** ******* *** *** ******"
$stringF = preg_replace('/[[:blank:]]/', '-', $stringA); // string(57) "1-In-the-beginning-God-created-the-heavens-and-the-earth."

$stringG = sprintf("垂直制表符: %s", chr(11)); // string(22) "Vertical Tabulation: "
$stringH = preg_replace('/[[:cntrl:]]/', '', $stringG); // string(21) "Vertical Tabulation: "
$stringLengthG = strlen($stringG); // int(22)
$stringLengthH = strlen($stringH); // int(21)

$stringI = preg_replace('/[[:digit:]]/', '', 'My age is 35'); //string(10) "My age is "
$stringJ = preg_replace('/[[:^digit:]]/', '', 'My age is 35'); // string(2) "35"

$stringK = preg_replace('/[[:^graph:]]/', '', $stringG); // string(19) "VerticalTabulation:"
$stringL = preg_replace('/[[:graph:]]/', '', $stringG); // string(3) " "

$stringM = preg_replace('/[[:lower:]]/', '', $stringG); // string(6) "V T: "
$stringN = preg_replace('/[[:^lower:]]/', '', $stringG); // string(16) "erticalabulation"

$stringO = preg_replace('/[[:^print:]]/', '', $stringG); // string(21) "Vertical Tabulation: "
$stringP = preg_replace('/[[:print:]]/', '', $stringG); // string(1) " "

$stringQ = preg_replace('/[[:punct:]]/', '', $stringG); // string(21) "Vertical Tabulation "
$stringR = preg_replace('/[[:^punct:]]/', '', $stringG); // string(1) ":"

$stringS = preg_replace('/[[:space:]]/', '', $stringG); // string(19) "VerticalTabulation:"
$stringT = preg_replace('/[[:^space:]]/', '', $stringG); // string(3) " "

$stringU = preg_replace('/[[:upper:]]/', '', $stringG); // string(20) "ertical abulation: "
$stringV = preg_replace('/[[:^upper:]]/', '', $stringG); // string(2) "VT"

$stringW = preg_replace('/[[:word:]]/', '', $stringG); // string(4) " : "
$stringX = preg_replace('/[[:^word:]]/', '', $stringG); // string(18) "VerticalTabulation"

$stringY = preg_replace('/[[:xdigit:]]/', '', 'abcdefghijklmnopqrstuvwxyz0123456789'); // string(20) "ghijklmnopqrstuvwxyz"
$stringZ = preg_replace('/[[:^xdigit:]]/', '', 'abcdefghijklmnopqrstuvwxyz0123456789'); // string(16) "abcdef0123456789"
[email protected]
6 年前
文档中说

"字符类型 \d、\D、\s、\S、\w 和 \W 也可以出现在字符类中,并将它们匹配的字符添加到类中。"

它没有强调其他转义类型可能不会。我想根据逗号 (",") 或换行符 ("\n") 分割字符串。当我的输入流开始包含 "\r\n" 时,我决定将 "\n" 更改为 "\R"。不幸的是,我的测试字符串不包含大写字母 "R",否则我可能早点发现问题。我的 '/[\R,]/' 只是在逗号和字母 "R" 上进行分割。

我的测试字符串...
"The Yum-Yum Company\r\n127 bernard street"

起作用的是:'/(?:\R|,)+/'

["The Yum-Yum Company","127 bernard street"]

鉴于字符类只匹配一个字符,我清楚地看到了为什么我的期望会落空,但希望这条评论能为其他人节省时间。

我可能要补充一点,这让我意识到了 PCRE_EXTRA(修饰符“X”)的价值,我现在已经开始常规地使用它了。
To Top