2024 日本 PHP 研討會

字元類別

一個左方括號表示字元類別的開始,並以右方括號結束。單獨的右方括號本身並不特殊。如果需要將右方括號作為類別的成員,它應該是類別中的第一個資料字元(在起始脫字符號之後,如果有的話)或使用反斜線進行跳脫。

字元類別會比對目標字串中的單個字元;該字元必須在類別定義的字元集中,除非類別中的第一個字元是脫字符號,在這種情況下,目標字元不得在類別定義的字元集中。如果實際需要將脫字符號作為類別的成員,請確保它不是第一個字元,或使用反斜線進行跳脫。

例如,字元類別 [aeiou] 匹配任何小寫母音,而 [^aeiou] 匹配任何非小寫母音的字元。請注意,抑揚符號(^)只是一種方便的表示法,用於指定類別中的字元,方法是列舉那些不在其中的字元。它並不是一種斷言:它仍然會從目標字串中取用一個字元,如果目前的指標位於字串的末尾,則會匹配失敗。

當設定為不區分大小寫(忽略大小寫)匹配時,類別中的任何字母都代表其大寫和小寫版本,因此,例如,不區分大小寫的 [aeiou] 匹配「A」和「a」,而不區分大小寫的 [^aeiou] 不匹配「A」,而區分大小寫的版本則會匹配「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僅限空格或 Tab
cntrl控制字元
digit十進位數字(與 \d 相同)
graph可列印字元,不包括空格
lower小寫字母
print可列印字元,包括空格
punct可列印字元,不包括字母和數字
space空白字元(與 \s 不完全相同)
upper大寫字母
word「word」字元(與 \w 相同)
十六進位數字 (xdigit)十六進位數字
space 字元包含 HT (9), LF (10), VT (11), FF (12), CR (13) 以及 space (32)。請注意此列表包含 VT 字元(代碼 11)。這使得「space」與 \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 年前
來自 PCRE 手冊深處:http://www.pcre.org/pcre.txt

\d 任何十進位數字
\D 任何非十進位數字的字元
\h 任何水平空白字元
\H 任何非水平空白字元的字元
\s 任何空白字元
\S 任何非空白字元的字元
\v 任何垂直空白字元
\V 任何非垂直空白字元的字元
\w 任何「word」字元
\W 任何「non-word」字元
Julian
1 年前
字元類別範例

<?php

$stringA
= "1 In the beginning God created the heavens and the earth.";
$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("Vertical Tabulation: %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"
wordragon at wrestingcontrol dot com
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