快速入門
教學
工具和語言
範例
參考
書籍評論
正規表示式工具
grep
PowerGREP
RegexBuddy
RegexMagic
一般應用程式
EditPad Lite
EditPad Pro
語言和程式庫
Boost
Delphi
GNU (Linux)
Groovy
Java
JavaScript
.NET
PCRE (C/C++)
PCRE2 (C/C++)
Perl
PHP
POSIX
PowerShell
Python
R
Ruby
std::regex
Tcl
VBScript
Visual Basic 6
wxWidgets
XML Schema
Xojo
XQuery 和 XPath
XRegExp
資料庫
MySQL
Oracle
PostgreSQL
本網站的更多內容
簡介
正規表示式快速入門
正規表示式教學
替換字串教學
應用程式和語言
正規表示式範例
正規表示式參考
替換字串參考
書籍評論
可列印 PDF
關於本網站
RSS Feed 和部落格
RegexBuddy—The best regex editor and tester for PCRE2 users!

PCRE2 開放原始碼正規表示式程式庫

PCRE2 是 Perl 相容正規表示式的簡稱,版本 2。它是廣受歡迎的 PCRE 程式庫的後繼版本。這兩個都是由 Philip Hazel 以 C 編寫的開放原始碼程式庫。

第一個 PCRE2 版本給予版本號碼 10.00,以與先前的 PCRE 8.36 明確區分。PCRE 8.37 到 8.44 和任何未來的 PCRE 版本都僅限於修正錯誤。新功能只會新增到 PCRE2。如果您要進行新的開發專案,您應該考慮使用 PCRE2,而不是 PCRE。但是對於已經使用 PCRE 的現有專案,最好還是堅持使用 PCRE。從 PCRE 移轉到 PCRE2 需要對您的原始碼進行重大變更。這樣做的唯一真正原因是使用新的搜尋和取代功能。

PHP 7.3.0 從 PCRE 移轉到 PCRE2,但沒有使用新的 PCRE2 搜尋和取代。它繼續使用 PHP 本身的替換文字語法。

R 4.0.0 也將其 grep 及相關函數從 PCRE 移至 PCRE2。其 subgsub 函數持續使用 R 本身的替換文字語法。

PCRE2 10.00 至 10.34 及 PCRE 8.36 至 8.44 支援的正規表示式語法大致相同。因此,本網站上 正規表示式教學 中關於 PCRE(或特別是 PCRE 版本 8.36 至 8.44)的說明也適用於 PCRE2。PCRE2 僅在與 PCRE 不同的幾個特定區域中被提及。

正規表示式語法有新的版本檢查條件。該語法很像 檢查命名反向參照的條件,但包含等號(以及擷取群組名稱中不允許的其他符號),使其在原始 PCRE 中成為語法錯誤。在所有版本的 PCRE2 中,(?(VERSION>=10.00)yes|no) 在字串 yesno 中比對 yes。您可以對「yes」和「no」部分使用任何有效的正規表示式。如果版本檢查成功,則會嘗試「yes」部分。否則,會嘗試「no」部分。這完全就像一個正常的條件,根據擷取群組是否參與比對,來評估直線符號前或後的部分。

您可以使用 >= 檢查最小版本,或使用 = 檢查特定版本。 (?(VERSION=10.00)yes|no) 在 PCRE2 10.00 中比對 yes。它在 PCRE2 10.10 和所有後續版本中比對 no。省略次要版本號碼與指定 .00 相同。因此,(?(VERSION>=10)yes|no) 在所有版本的 PCRE2 中比對 yes,但 (?(VERSION=10)yes|no) 僅在 PCRE2 10.00 中比對 yes。如果您指定次要版本號碼,您應該在小數點後使用兩個數字。從版本 10.21 開始,三個或更多數字會產生錯誤。版本 10.21 也變更了個位數數字的詮釋,包括以零開頭的數字。由於第一個版本是 10.00,第二個版本是 10.10,因此不需要檢查個位數數字。如果您指定次要版本號碼,您不能省略小數點。 (?(VERSION>=1000)yes|no) 檢查版本 1000.00 或更高。

此版本檢查條件主要適用於間接使用 PCRE2 的人,透過提供基於 PCRE2 的正規表示式支援或嵌入 PCRE2 但不公開其所有函式呼叫的應用程式或程式語言。它允許他們找出應用程式使用的 PCRE2 版本。如果您使用 PCRE2 C 函式庫開發應用程式,則您應該使用函式呼叫來確定 PCRE2 版本。

char version[255];
pcre2_config(PCRE2_CONFIG_VERSION, version);

UTF-8、UTF-16 或 UTF-32

在原始的 PCRE 函式庫中,UTF-16 和 UTF-32 支援是在後續版本中透過附加函式新增的,這些函式以 pcre16_ 和 pcre32_ 為字首。在 PCRE2 中,所有函式都以 pcre2_ 為字首,並以 _8、_16 或 _32 為字尾,以選取 8 位元、16 位元或 32 位元程式碼單位。如果您從原始碼編譯 PCRE2,您需要將 --enable-pcre2-16--enable-pcre2-32 傳遞給 configure 指令碼,以確保 _16 和 _32 函式可用。

8 位元、16 位元或 32 位元程式碼單位表示 PCRE2 會將您的字串解釋為由單位元組字元、雙位元組字元或四位元組字元組成。若要使用 UTF-8、UTF-16 或 UTF-32,您需要使用具有對應程式碼單位大小的函式,並將 PCRE2_UTF 選項傳遞給 pcre2_compile,以允許字元由多個程式碼單位組成。UTF-8 字元由 1 到 4 個位元組組成。UTF-16 字元由 1 或 2 個字組成。

如果您想要在沒有任何字尾的情況下呼叫 PCRE2 函式,如下所示,那麼您需要將 PCRE2_CODE_UNIT_WIDTH 定義為 8、16 或 32,以使沒有字尾的函式使用 8 位元、16 位元或 32 位元程式碼單位。在包含函式庫之前執行此操作,如下所示

#define PCRE2_CODE_UNIT_WIDTH 8
#include "pcre2.h"

沒有字尾的函式始終使用您定義的程式碼單位大小。具有字尾的函式仍然可用。因此,您的應用程式可以使用具有所有三種程式碼單位大小的正規表示式。但重要的是不要將它們混淆。如果需要將相同的正規表示式與 UTF-8 和 UTF-16 字串比對,則您需要使用 pcre_compile_8 和 pcre_compile_16 編譯它兩次,然後使用對應的 pcre_match_8 和 pcre_match_16 函式使用已編譯的正規表示式。

使用 PCRE2

使用 PCRE2 比使用 PCRE 稍微複雜一些。使用 PCRE2 時,您必須使用各種類型的內容傳遞某些編譯或比對選項,例如換行處理。在 PCRE 中,這些選項可以在編譯或比對時直接傳遞為選項位元。

在使用正規表示式之前,需要將其轉換為二進位格式以提升效率。為此,只需呼叫 pcre2_compile(),並將正規表示式作為字串傳遞。如果字串以 null 結束,則可以將 PCRE2_ZERO_TERMINATED 傳遞為第二個參數。否則,請將長度傳遞為第二個參數中的程式碼單位。對於 UTF-8,這是以位元組為單位的長度,而對於 UTF-16 或 UTF-32,這是以位元組長度除以 2 或 4。第三個參數是一組選項,與二進位或結合。您應該包含 PCRE2_UTF 以獲得適當的 UTF-8、UTF-16 或 UTF-32 支援。如果您省略它,您將獲得純 8 位元、或 UCS-2 或 UCS-4 字元處理。其他常見選項包括 PCRE2_CASELESS、PCRE2_DOTALL、PCRE2_MULTILINE 等。第四和第五個參數接收錯誤條件。最後一個參數是內容。除非您需要特殊換行處理,否則傳遞 NULL。當您完成正規表示式時,函式會傳回指標至其配置的記憶體。您必須使用 pcre2_code_free() 釋放此記憶體。

如果您需要非預設換行處理,您需要呼叫 pcre2_compile_context_create(NULL) 來建立新的編譯內容。然後呼叫 pcre2_set_newline() 傳遞該內容和選項之一,例如 PCRE2_NEWLINE_LF 或 PCRE2_NEWLINE_CRLF。然後將此內容作為最後一個參數傳遞至 pcre2_compile()。您可以對任意數量的正規表示式編譯重複使用相同的內容。當您完成後,請呼叫 pcre2_compile_context_free()。請注意,在原始 PCRE 中,您可以將 PCRE_NEWLINE_LF 等直接傳遞至 pcre_compile()。這不適用於 PCRE2。如果您將 PCRE2_NEWLINE_LF 等傳遞至 pcre2_compile(),PCRE2 也不會抱怨。但這樣做沒有效果。您必須使用比對內容。

在使用已編譯的正規表示式尋找字串中的配對之前,您需要呼叫 pcre2_match_data_create_from_pattern() 來配置儲存配對結果的記憶體。將已編譯的正規表示式傳遞為第一個參數,並將 NULL 傳遞為第二個參數。此函式會傳回已配置記憶體的指標。當您完成配對資料時,您必須使用 pcre2_match_data_free() 釋放此記憶體。您可以重複使用相同的配對資料來多次呼叫 pcre2_match()。

若要尋找配對,請呼叫 pcre2_match() 並傳遞已編譯的正規表示式、主旨字串、整個字串的長度、配對嘗試必須開始的字元的偏移量、配對選項、配對資料物件的指標,以及 NULL 作為內容。長度和起始偏移量以程式碼單位表示,而非字元。當配對成功時,此函式會傳回正數。PCRE2_ERROR_NOMATCH 表示未找到配對。任何其他非正回傳值表示錯誤。可以使用 pcre2_get_error_message() 取得錯誤訊息。

若要找出字串的哪一部分配對,請呼叫 pcre2_get_ovector_pointer()。這會傳回 PCRE2_SIZE 值陣列的指標。您不需要釋放此指標。當您呼叫 pcre2_match_data_free() 時,它將會失效。陣列的長度是 pcre2_match() 傳回的值。陣列中的前兩個值是整體配對的開始和結束。第二對是第一個擷取群組的配對,依此類推。如果您的正規表示式有命名擷取群組,請呼叫 pcre2_substring_number_from_name() 來取得群組號碼。

如果您只想取得配對的文字,您可以使用便利函式,例如 pcre2_substring_copy_bynumber() 或 pcre2_substring_copy_byname()。傳遞擷取群組的號碼或名稱,或傳遞零表示整體配對。使用 pcre2_substring_free() 釋放結果。如果結果不需要以零終止,您可以使用 pcre2_substring_get_bynumber() 和 pcre2_substring_get_byname() 來取得原始主旨字串中配對開始位置的指標。pcre2_substring_length_bynumber() 和 pcre2_substring_length_byname() 會提供配對的長度。

PCRE2 沒有提供函式讓您取得字串中正規表示式的所有配對。它永遠只會傳回第一個配對。若要取得第二個配對,請再次呼叫 pcre2_match() 並傳遞 ovector[1](第一個配對的結束)作為第二個配對嘗試的起始位置。如果第一個配對為零長度,請在傳遞給 pcre2_match() 的選項中包含 PCRE2_NOTEMPTY_ATSTART,以避免再次找到相同的零長度配對。這與在呼叫之前遞增起始位置不同。使用 PCRE2_NOTEMPTY_ATSTART 傳遞前一個配對的結束可能會導致在相同位置找到非零長度的配對。

取代配對

PCRE 願望清單中永遠最大的項目可能是搜尋和取代功能。PCRE2 終於實現了。取代字串語法相當簡單。不過,它與 Perl 不相容。反向參照可以指定為 $group${group},其中「group」是群組的名稱或編號。整體比對是群組編號 0。若要將文字美元符號新增至取代字串,您需要重複輸入。任何不屬於有效反向參照的單一美元符號都是錯誤。與 Python 相似,但與 Perl 不同,PCRE2 將 不存在群組的反向參照不參與群組的反向參照 視為錯誤。反斜線是文字。

在您可以取代比對之前,您需要使用 pcre2_compile() 編譯正規表示式。您可以將相同的編譯正規表示式用於正規表示式比對和正規表示式取代。您不需要比對資料物件進行取代。

呼叫 pcre2_substitute(),並傳遞編譯的正規表示式、主旨字串、主旨字串的長度、正規表示式比對應從字串中的哪個位置開始,以及比對選項。您可以將 PCRE2_SUBSTITUTE_GLOBAL 與比對選項搭配使用,以取代起始位置之後的所有比對,而不仅仅是第一個比對。下一個參數用於比對資料和比對內容,兩者都可以設定為 NULL。然後傳遞取代字串和取代字串的長度。最後傳遞結果字串應儲存的緩衝區指標,以及儲存緩衝區大小的變數指標。緩衝區需要有空間存放終止零。所有長度和偏移量都以程式碼單位為單位,而非字元。

pcre2_substitute() 傳回已取代的正規表示式比對數。零表示未找到任何比對。此函數絕不會傳回 PCRE2_ERROR_NOMATCH。負數表示發生錯誤。呼叫 pcre2_get_error_message() 以取得錯誤訊息。儲存緩衝區大小的變數會更新,以指出寫入緩衝區的字串長度,不包括終止零。(會寫入終止零。)

延伸取代字串語法

從版本 10.21 開始,PCRE2 提供延伸取代字串語法,您可以在呼叫 pcre2_substitute() 時將 PCRE2_SUBSTITUTE_EXTENDED 與比對選項搭配使用,以啟用此語法。最大的不同是反斜線不再是文字。反斜線後接非字母或數字的字元會跳脫該字元。因此,您可以使用其他反斜線跳脫美元符號和反斜線,以取消它們的特殊意義。如果您要在取代字串中使用文字反斜線,則必須使用另一個反斜線跳脫它。反斜線後接數字是錯誤。反斜線後接字母是錯誤,除非該組合形成取代字串代碼。

\a\e\f\n\r\t 是常見的 ASCII 控制字元跳脫字元。特別注意的是,\b\v 不見了。 \x0\xF\x00\xFF 是十六進位跳脫字元。 \x{0}\x{10FFFF} 會插入 Unicode 編碼點。 \o{0}\o{177777} 是八進位跳脫字元。

大小寫轉換 也受支援。語法與 Perl 相同,但行為不同。Perl 允許您將 \u\l\L\U 結合,使一個字元變成大寫或小寫,而其餘的字元則相反。使用 PCRE2,任何大小寫轉換跳脫字元都會取消前一個跳脫字元。因此,您無法將它們結合,甚至 \u\l 都會結束 \U\L 的執行。

條件 使用新發明的語法來支援,該語法擴充了反向參照的語法。 ${group:+已比對:未比對} 會在群組參與時插入 已比對,在群組未參與時插入 未比對。您可以在兩個選項中使用完整的替換字串語法,包括其他條件。

大小寫轉換會執行條件。條件之前有效的任何大小寫轉換也會套用於條件。如果條件包含其自己的大小寫轉換跳脫字元,則這些跳脫字元會在條件之後仍然有效。因此,您可以使用 ${1:+\U:\L}${2} 來插入第二個擷取群組比對到的文字,如果第一個群組有參與,則為大寫;如果第一個群組未參與,則為小寫。

| 快速入門 | 教學 | 工具和語言 | 範例 | 參考 | 書籍評論 |

| grep | PowerGREP | RegexBuddy | RegexMagic |

| EditPad Lite | EditPad Pro |

| Boost | Delphi | GNU (Linux) | Groovy | Java | JavaScript | .NET | PCRE (C/C++) | PCRE2 (C/C++) | Perl | PHP | POSIX | PowerShell | Python | R | Ruby | std::regex | Tcl | VBScript | Visual Basic 6 | wxWidgets | XML Schema | Xojo | XQuery & XPath | XRegExp |

| MySQL | Oracle | PostgreSQL |