正則表達式

正則表達式（regular expression，常簡寫為regex、regexp或RE），又稱規律表達式、正規表達式、正規表示法、規則運算式、常規表示法，是電腦科學概念，用簡單字串來描述、匹配文中全部符合指定格式的字串，現在很多文本編輯器都支援用正則表達式搜尋、取代符合指定格式的字串。

許多程序設計語言都支援用正則表達式操作字串，如Perl就內建功能強大的正則表達式引擎。正則表達式這概念最初由Unix的工具軟體（例如sed和grep）普及開。

## 譯名問題

描述字串規律的表達式原應順理成章稱為規律表達式（pattern expression／rule expression），但卻叫成有欠準確的regular expression，導致現在有多種中譯名，如將regular譯成規律、規則、正則、正則或常規，將expression譯成表達式、表達式、表示法或運算式等。

## 歷史

最初的正則表達式出現於理論電腦科學的自動控制理論和形式化語言理論中。在這些領域中有對計算（自動控制）的模型和對形式化語言描述與分類的研究。

1940年，沃倫·麥卡洛克與沃爾特·皮茨將神經系統中的神經元描述成小而簡單的自動控制元。

1950年代，數學家史蒂芬·科爾·克萊尼利用稱之為「正則集合」的數學符號來描述此模型。肯·湯普遜將此符號系統引入編輯器QED (文字編輯器)，隨後是Unix上的編輯器ed，並最終引入grep。自此以後，正則表達式被廣泛地應用於各種Unix或類Unix系統的工具中。正則表達式的POSIX規範，分為基本型正則表達式（Basic Regular Expression，BRE）和擴展型正則表達式（Extended Regular Expression，ERE）兩大流派。在兼容POSIX的UNIX系統上，grep和egrep之類的工具都遵循POSIX規範，一些資料庫系統中的正則表達式也符合POSIX規範。grep、vi、sed都屬於BRE，是歷史最早的正則表達式，因此元字符必須轉譯之後才具有特殊含義。egrep、awk則屬於ERE，元字符不用轉譯。

Perl的正則表達式源自於Henry Spencer於1986年1月19日發布的regex，它已經演化成了PCRE（Perl兼容正則表達式，Perl Compatible Regular Expressions），一個由Philip Hazel開發的，為很多現代工具所使用的庫。

各編程語言之間關於正則表達式的整合，目前開發進展得很差。Perl6的子項目Apocalypse的設計中已考慮到了這點。

## 理論

正則表達式可以用形式化語言理論的方式來表達。正則表達式由常量和算子組成，它們分別表示字串的集合和在這些集合上的運算。給定有限字母表Σ定義了下列常量：

- 空集$\varnothing$表示集合為空。
- 空串$\varepsilon$表示僅包含一個「不含任何字符、長度為0的字串」的集合。
- 字串文字$a\in\Sigma$表示僅包含一個元素$a$的集合$\{a\}$。

定義了下列運算：

- 串接 $RS$表示集合$\{\alpha \beta \mid \alpha \in R, \beta \in S\}$，這裡的$\alpha \beta$表示將$\alpha$和$\beta$兩個字串按順序連接。例如：$\{ab, c\}\{d, ef\} = \{abd, abef, cd, cef\}$。
- 選擇 $R | S$表示$R$和$S$的併集。例如：$\{ab, c\} | \{ab, d, ef\} = \{ab, c, d, ef\}$。
- 克萊尼(Kleene)星號 $R^*$表示包含$\varepsilon$且在字串串接運算下閉合的$R$的最小超集。這是可以通過$R$中零或有限個字串的串接得到所有字串的集合。例如：$\{ab, c\}^* = \{\varepsilon, ab, c, abab, abc, cab, cc, ababab, \cdots \}$。

上述常量和算子形成了克萊尼代數。

很多課本使用對選擇使用符號$\cup$、$+$或$\vee$替代豎線。

為了避免括號，假定Kleene星號有最高優先級，接著是串接，接著是併集。如果沒有歧義則可以省略括號。例如：`(ab)c`可以寫為`abc`，而`a|(b(c*))`可以寫為`a|bc*`。

例子：

- `a|b*`表示$\{\varepsilon, a, b, bb, bbb, \cdots \}$。
- `(a|b)*`表示包括空串和任意數目個a或b字符組成的所有字串的集合：$\{\varepsilon, a, b, aa, ab, ba, bb, aaa \cdots \}$。
- `ab*(c|ε)`表示開始於一個a接著零或多個b和最後一個可選的c組成的字串的集合：$\{a, ac, ab, abc, abb, abbc \cdots \}$。

為了使表達式更簡潔，正則表達式也定義了`?`和`+`；`aa*`等於`a+`，表示a出現至少一次；而`(a|ε)`等於`a?`，表示a出現1次或不出現。有的定義中增加了補算子$\sim$；$\sim R$表示在$\Sigma^*$上但不在$R$中的所有字串的集合。補算子在理論上並非必要，因為它可以使用其他算子來表達，但它可以使一些表達式變得更加簡潔。

這種意義上的正則表達式可以表達正則語言，是可被有限狀態自動機精確接受的語言類。但是在簡潔性上有重要區別。某類正則語言只能用大小指數增長的自動機來描述，而要求的正則表達式的長度只線性的增長。

正則表達式對應於喬姆斯基層級的類型-3文法。但通常程式語言或其相關庫（例如PCRE）中實現的正則表達式的表達能力是喬姆斯基層級中類型-3文法的超集。在另一方面，在正則表達式和不導致這種大小上的爆炸的非確定有限狀態自動機（NFA）之間有簡單的映射；為此NFA經常被用作正則表達式的替表示式。

這種形式化中存在著冗餘。典型的體現是，同樣的語言可以用不同的正則表達式表達。對於兩個給定的正則表達式，給出一個演算法來判定它們所描述的語言是否相等，即簡約每個表達式到極小確定有限自動機，確定它們是否同構（等價）。這種冗餘最多可以減少到什麼程度？存在具有完全表達力的正則表達式的最小子集嗎？這是一個極為困難的問題。我們需要Kleene星號和併集來解決這些問題，但是我們可以限制它們的使用。由於正則表達式的簡單性，不存在其他辦法可以將其在語法上重寫成某種規範形式。過去公理化的缺乏導致了星號高度問題。近期，Dexter Kozen用克萊尼代數公理化了正則表達式。

很多現實世界的「正則表達式」引擎實現了不能用正則表達式代數表達的特徵。

## 基本語法

一個正則表達式通常被稱為一個模式（pattern），為用來描述或者匹配一系列符合某個句法規則的字串。例如：Handel、Händel和Haendel這三個字串，都可以由`H(a|ä|ae)ndel`這個模式來描述。大部分正則表達式的形式都有如下的結構：

### 選擇

- 豎線`|`代表選擇（即或集），具有最低優先級。例如`gray|grey`可以匹配grey或gray。

### 數量限定

某個字符後的數量限定符用來限定前面這個字符允許出現的個數。最常見的數量限定符包括`+`、`?`和`*`（不加數量限定則代表出現一次且僅出現一次）：

- 加號`+`代表前面的字符必須至少出現一次。（1次或多次）。例如，`goo+gle`可以匹配google、gooogle、goooogle等。
- 問號`?`代表前面的字符最多只可以出現一次。（0次或1次）。例如，`colou?r`可以匹配color或者colour。
- 星號`*`代表前面的字符可以不出現，也可以出現一次或者多次。（0次、1次或多次）。例如，`0*42`可以匹配42、042、0042、00042等。

### 匹配

- 圓括號`()`可以用來定義操作符的範圍和優先度。例如，`gr(a|e)y`等價於`gray|grey`，`(grand)?father`匹配father和grandfather。

上述這些構造子都可以自由組合，因此`H(ae?|ä)ndel`和`H(a|ae|ä)ndel`是相同的，表示{"Handel", "Haendel", "Händel"}。

精確的語法可能因不同的工具或程序而異。

## PCRE表達式全集

正則表達式有多種不同的風格。下表是在PCRE中元字符及其在正則表達式上下文中的行為的一個完整列表，適用於Perl或者Python程式語言（grep或者egrep的正則表達式文法是PCRE的子集）：

字符｜描述

`\`｜將下一個字符標記為一個特殊字符（File Format Escape，清單見本表）、或一個原義字符（Identity Escape，有「`^$()*+?.[\{|`」共計12個）、或一個向後引用（backreferences）、或一個八進位轉義符。例如，「`n`」匹配字符「`n`」。「`\n`」匹配一個換行符。序列「`\\`」匹配「`\`」而「`\(`」則匹配「`(`」。

`^`｜匹配輸入字串的開始位置。如果設置了RegExp對象的Multiline屬性，^也匹配「`\n`」或「`\r`」之後的位置。

`$`｜匹配輸入字串的結束位置。如果設置了RegExp對象的Multiline屬性，$也匹配「`\n`」或「`\r`」之前的位置。

`*`｜匹配前面的子表達式零次或多次。例如，zo、能匹配「`z`」、「`zo`」以及「`zoo`」。、等價於{0,}。

`+`｜匹配前面的子表達式一次或多次。例如，「`zo+`」能匹配「`zo`」以及「`zoo`」，但不能匹配「`z`」。+等價於{1,}。

`?`｜匹配前面的子表達式零次或一次。例如，「`do(es)?`」可以匹配「`does`」中的「`do`」和「`does`」。?等價於{0,1}。

`{<span style="font-family:Times New Roman; font-style:italic;">n</span>}`｜n是一個非負整數。匹配確定的n次。例如，「`o{2}`」不能匹配「`Bob`」中的「`o`」，但是能匹配「`food`」中的兩個o。

`{<span style="font-family:Times New Roman; font-style:italic;">n</span>,}`｜n是一個非負整數。至少匹配n次。例如，「`o{2,}`」不能匹配「`Bob`」中的「`o`」，但能匹配「`foooood`」中的所有o。「`o{1,}`」等價於「`o+`」。「`o{0,}`」則等價於「`o*`」。

`{<span style="font-family:Times New Roman; font-style:italic;">n</span>,<span style="font-family:Times New Roman; font-style:italic;">m</span>}`｜m和n均為非負整數，其中n<=m。最少匹配n次且最多匹配m次。例如，「`o{1,3}`」將匹配「`fooooood`」中的前三個o。「`o{0,1}`」等價於「`o?`」。請注意在逗號和兩個數之間不能有空格。

`?`｜非貪心量化（Non-greedy quantifiers）：當該字符緊跟在任何一個其他重複修飾符（、,+,?，{n}，{n,}，{n,m}）後面時，匹配模式是非貪婪的。非貪婪模式儘可能少的匹配所搜索的字串，而默認的貪婪模式則儘可能多的匹配所搜索的字串。例如，對於字串「`oooo`」，「`o+?`」將匹配單個「`o`」，而「`o+`」將匹配所有「`o`」。

`.`｜匹配除「`\r`」「`\n`」之外的任何單個字符。要匹配包括「`\r`」「`\n`」在內的任何字符，請使用像「`(.|\r|\n)`」的模式。

`(pattern)`｜匹配pattern並獲取這一匹配的子字串。該子字串用於向後引用。所獲取的匹配可以從產生的Matches集合得到，在VBScript中使用SubMatches集合，在JScript中則使用$0...$9屬性。要匹配圓括號字符，請使用「`\(`」或「`\)`」。可帶數量後綴。

`(?:pattern)`｜匹配pattern但不獲取匹配的子字串（shy groups），也就是說這是一個非獲取匹配，不存儲匹配的子字串用於向後引用。這在使用或字符「`(|)`」來組合一個模式的各個部分是很有用。例如「`industr(?:y|ies)`」就是一個比「`industry|industries`」更簡略的表達式。

`(?=pattern)`｜正向肯定預查（look ahead positive assert），在任何匹配pattern的字串開始處匹配查找字串。這是一個非獲取匹配，也就是說，該匹配不需要獲取供以後使用。例如，「`Windows(?=95|98|NT|2000)`」能匹配「`Windows2000`」中的「`Windows`」，但不能匹配「`Windows3.1`」中的「`Windows`」。預查不消耗字符，也就是說，在一個匹配發生後，在最後一次匹配之後立即開始下一次匹配的搜索，而不是從包含預查的字符之後開始。

`(?!pattern)`｜正向否定預查（negative assert），在任何不匹配pattern的字串開始處匹配查找字串。這是一個非獲取匹配，也就是說，該匹配不需要獲取供以後使用。例如「`Windows(?!95|98|NT|2000)`」能匹配「`Windows3.1`」中的「`Windows`」，但不能匹配「`Windows2000`」中的「`Windows`」。預查不消耗字符，也就是說，在一個匹配發生後，在最後一次匹配之後立即開始下一次匹配的搜索，而不是從包含預查的字符之後開始

`(?<=pattern)`｜反向（look behind）肯定預查，與正向肯定預查類似，只是方向相反。例如，「`(?<=95|98|NT|2000)Windows`」能匹配「`2000Windows`」中的「`Windows`」，但不能匹配「`3.1Windows`」中的「`Windows`」。

`(?<!pattern)`｜反向否定預查，與正向否定預查類似，只是方向相反。例如「`(?<!95|98|NT|2000)Windows`」能匹配「`3.1Windows`」中的「`Windows`」，但不能匹配「`2000Windows`」中的「`Windows`」。

`x|y`｜匹配x或y。總是先嘗試匹配左邊的表達式。如果 | 沒有包圍在里，其範圍是整個正則表達式。例如，「`z|food`」能匹配「`z`」或「`food`」。「`(?:z|f)ood`」則匹配「`zood`」或「`food`」。

`[xyz]`｜字符集合（character class）。匹配所包含的任意一個字符。例如，「`[abc]`」可以匹配「`plain`」中的「`a`」。特殊字符僅有反斜線\保持特殊含義，用於轉義字符。其它特殊字符如星號、加號、各種括號等均作為普通字符。脫字符^如果出現在首位則表示負值字符集合；如果出現在字串中間就僅作為普通字符。連字符 - 如果出現在字串中間表示字符範圍描述；如果如果出現在首位（或末尾）則僅作為普通字符。右方括號應轉義出現，也可以作為首位字符出現。

`[^xyz]`｜排除型字符集合（negated character classes）。匹配未列出的任意字符。例如，「`[^abc]`」可以匹配「`plain`」中的「`plin`」。

`[a-z]`｜字符範圍。匹配在Unicode編碼表指定範圍內的任意字符。例如，「`[a-z]`」可以匹配「`a`」到「`z`」範圍內的任意小寫字母字符。

`[^a-z]`｜排除型的字符範圍。匹配任何不在Unicode編碼表指定範圍內的任意字符。例如，「`[^a-z]`」可以匹配任何不在「`a`」到「`z`」範圍內的任意字符。

`[:name:]`｜增加命名字符類（named character class）中的字符到表達式。只能用於方括號表達式。

`[=elt=]`｜增加當前locale下排序（collate）等價於字符「elt」的元素。例如，=a=可能會增加ä、á、à、ă、ắ、ằ、ẵ、ẳ、â、ấ、ầ、ẫ、ẩ、ǎ、å、ǻ、ä、ǟ、ã、ȧ、ǡ、ą、ā、ả、ȁ、ȃ、ạ、ặ、ậ、ḁ、ⱥ、ᶏ、ɐ、ɑ。只能用於方括號表達式。

`[.elt.]`｜增加排序元素（collation element）elt到表達式中。這是因為某些排序元素由多個字符組成。例如，29個字母表的西班牙語， "CH"作為單個字母排在字母C之後，因此會產生如此排序「cinco, credo, chispa」。只能用於方括號表達式。

`\b`｜匹配一個單詞邊界，也就是指單詞和空格間的位置。例如，「`er\b`」可以匹配「`never`」中的「`er`」，但不能匹配「`verb`」中的「`er`」。

`\B`｜匹配非單詞邊界。「`er\B`」能匹配「`verb`」中的「`er`」，但不能匹配「`never`」中的「`er`」。

`\cx`｜匹配由x指明的控制字符。x的值必須為`A-Z`或`a-z`之一。否則，將c視為一個原義的「`c`」字符。控制字符的值等於x的值最低5比特（即對3210進位的餘數）。例如，\cM匹配一個Control-M或回車符。\ca等效於\u0001, \cb等效於\u0002, 等等...

`\d`｜匹配一個數字字符。等價於0-9。注意Unicode正則表達式會匹配全形數字字符。

`\D`｜匹配一個非數字字符。等價於^0-9。

`\f`｜匹配一個換頁符。等價於\x0c和\cL。

`\n`｜匹配一個換行符。等價於\x0a和\cJ。

`\r`｜匹配一個回車符。等價於\x0d和\cM。

`\s`｜匹配任何空白字符，包括空格、制表符、換頁符等等。等價於 \f\n\r\t\v。注意Unicode正則表達式會匹配全形空格符。

`\S`｜匹配任何非空白字符。等價於^ \f\n\r\t\v。

`\t`｜匹配一個制表符。等價於\x09和\cI。

`\v`｜匹配一個垂直制表符。等價於\x0b和\cK。

`\w`｜匹配包括下劃線的任何單詞字符。等價於「`[A-Za-z0-9_]`」。注意Unicode正則表達式會匹配中文字符。

`\W`｜匹配任何非單詞字符。等價於「`[^A-Za-z0-9_]`」。

`\x<span style="font-family:Times New Roman; font-style:italic;">nn</span>`｜十六進位轉義字符序列。匹配兩個十六進位數字nn表示的字符。例如，「`\x41`」匹配「`A`」。「`\x041`」則等價於「`\x04&1`」。正則表達式中可以使用ASCII編碼。.

`\<span style="font-family:Times New Roman; font-style:italic;">num</span>`｜向後引用（back-reference）一個子字串（substring），該子字串與正則表達式的第num個用括號圍起來的捕捉群（capture group）子表達式（subexpression）匹配。其中num是從1開始的十進位正整數，其上限可能是9、31、99甚至無限。例如：「`(.)\1`」匹配兩個連續的相同字符。

`\<span style="font-family:Times New Roman; font-style:italic;">n</span>`｜標識一個八進位轉義值或一個向後引用。如果\n之前至少n個獲取的子表達式，則n為向後引用。否則，如果n為八進位數字（0-7），則n為一個八進位轉義值。

`\<span style="font-family:Times New Roman; font-style:italic;">nm</span>`｜3位八進位數字，標識一個八進位轉義值或一個向後引用。如果\nm之前至少有nm個獲得子表達式，則nm為向後引用。如果\nm之前至少有n個獲取，則n為一個後跟文字m的向後引用。如果前面的條件都不滿足，若n和m均為八進位數字（0-7），則\nm將匹配八進位轉義值nm。

`\<span style="font-family:Times New Roman; font-style:italic;">nml</span>`｜如果n為八進位數字（0-3），且m和l均為八進位數字（0-7），則匹配八進位轉義值nml。

`\u<span style="font-family:Times New Roman; font-style:italic;">n</span>`｜Unicode轉義字符序列。其中n是一個用四個十六進位數字表示的Unicode字符。例如，\u00A9匹配版權符號（©）。

## Unicode處理

在.NET、Java、JavaScript、Python的正則表達式中，可以用`\uXXXX`表示一個Unicode字符，其中`XXXX`為四位16進位數字。

Unicode字符的三種性質：

- Unicode Property：字符屬於標點、空格、字母等等。每個Unicode字符只能屬於唯一Unicode Property。.NET、Java、PHP和Ruby等語言支持。具體分類為：
- 字符`\p{L}`
- `\p{Ll}`或`\p{Lowercase_Letter}`：小寫字符（必須有大寫的形式）。
- `\p{Lu}`或`\p{Uppercase_Letter}`：大寫字符（必須有小寫的形式）。
- `\p{Lt}`或`\p{Titlecase_Letter}`：全詞首字母大寫的字符。
- `\p{L&}`或`\p{Cased_Letter}`：存在大小寫形式的字符（Ll, Lu, Lt的組合）。
- `\p{Lm}`或`\p{Modifier_Letter}`：音標修飾字符。
- `\p{Lo}`或`\p{Other_Letter}`：不具有大小寫的字符或字形。
- 附加符號`\p{M}`
- `\p{Mn}`或`\p{Non_Spacing_Mark}`：與其他字符結合，不額外占用空間的字符，例如日耳曼語元音變音。
- `\p{Mc}`或`\p{Spacing_Combining_Mark}`：與其他字符結合，額外占用空間的字符，例如馬拉雅拉姆文#元音字母及附標。
- `\p{Me}`或`\p{Enclosing_Mark}`：包含其他字符的字符，例如圓圈、方塊。
- 分隔符`\p{Z}`
- `\p{Zs}`或`\p{Space_Separator}`：不可見的空格，但占據空間。
- `\p{Zl}`或`\p{Line_Separator}`：分隔綫字符U+2028。
- `\p{Zp}`或`\p{Paragraph_Separator}`：分段字符U+2029。
- 符號`\p{S}`
- `\p{Sm}`或`\p{Math_Symbol}`：數學符號。
- `\p{Sc}`或`\p{Currency_Symbol}`：通貨符號。
- `\p{Sk}`或`\p{Modifier_Symbol}`：組合為其他字符的符號。
- `\p{So}`或`\p{Other_Symbol}`：其他符號。
- 數值字符`\p{N}`
- `\p{Nd}`或`\p{Decimal_Digit_Number}`：所有文本中的數字0至9字符，不含形意符號。
- `\p{Nl}`或`\p{Letter_Number}`：看起來像字母的符號，包含羅馬數字。
- `\p{No}`或`\p{Other_Number}`：上角標或下角標數字，或者其他不屬於0至9的數字。不含形意符號。
- 標點符號`\p{P}`
- `\p{Pd}`或`\p{Dash_Punctuation}`：任何種類的連字號或連接號。
- `\p{Ps}`或`\p{Open_Punctuation}`：任何種類開括號。
- `\p{Pe}`或`\p{Close_Punctuation}`：任何種類閉括號。
- `\p{Pi}`或`\p{Initial_Punctuation}`：任何種類開引號。
- `\p{Pf}`或`\p{Final_Punctuation}`：任何種類閉引號。
- `\p{Pc}`或`\p{Connector_Punctuation}`：連接詞的標點符號，如下劃線。
- `\p{Po}`或`\p{Other_Punctuation}`：其他標點符號。
- 其它符號`\p{C}`（包括不可見控制字符與未用碼位）
- `\p{Cc}`或`\p{Control}`：ASCII或Latin-1控制字符`0x00-0x1F`與`0x7F-0x9F`。
- `\p{Cf}`或`\p{Format}`：不可見的格式化指示字符。
- `\p{Co}`或`\p{Private_Use}`：私用碼位。
- `\p{Cs}`或`\p{Surrogate}`：UTF-16編碼的代理對的一半。
- `\p{Cn}`或`\p{Unassigned}`：未被使用的碼位。
- Unicode Block：按照編碼區間劃分Unicode字符，每個Unicode Block中的字符編碼屬於一個編碼區間。例如Java語言`\p{ InCJK_Compatibility_Ideographs }`，.NET語言`\p{IsCJK_Compatibility_Ideographs}`。
- Unicode Script：按照字符所屬的書寫系統來劃分Unicode字符。PHP和Ruby（版本不低於1.9）支持Unicode Script。例如`\p{Han}`表示漢字（中文字符）。

這三種Unicode性質對應的字符組補集是將開頭的`\p`改為`\P`，其它不變。

## POSIX字符組

POSIX字符組｜說明｜ASCII環境｜Unicode環境

`[:alnum:]`｜字母字符和數字字符｜`[a-zA-Z0-9]`｜`[\p{L&}\p{Nd}]`

`[:alpha:]`｜字母｜`[a-zA-Z]`｜`\p{L&}`

`[:ascii:]`｜ASCII字符｜`[\x00-\x7F]`｜`\p{InBasicLatin}`

`[:blank:]`｜空格字符和制表符｜`[ \t]`｜`[\p{Zs}\t]`

`[:cntrl:]`｜控制字符｜`[\x00-\x1F\x7F]`｜`\p{Cc}`

`[:digit:]`｜數字字符｜`[0-9]`｜`\p{Nd}`

`[:graph:]`｜空白字符之外的字符｜`[\x21-\x7E]`｜`[^\p{Z}\p{C}]`

`[:lower:]`｜小寫字母字符｜`[a-z]`｜`\p{Ll}`

`[:print:]`｜類似`[:graph:]`，但包括空白字符｜`[\x20-\x7E]`｜`[^\P{C}]`

`[:punct:]`｜標點符號｜}~-｜`[\p{P}\p{S}]`

`[:space:]`｜空白字符｜`[ \t\r\n\v\f]`｜`[\p{Z}\t\r\n\v\f]`

`[:upper:]`｜大寫字母字符｜`[A-Z]`｜`\p{Lu}`

`[:word:]`｜字母字符｜`[A-Za-z0-9_]`｜`[\p{L}\p{N}\p{Pc}]`

`[:xdigit:]`｜十六進位字符｜`[A-Fa-f0-9]`｜`[A-Fa-f0-9]`

## 優先權

優先權｜符號

最高｜`\`

高｜`()`、`(?:)`、`(?=)`、`[]`

中｜`*`、`+`、`?`、`{<span style="font-family:Times New Roman; font-style:italic;">n</span>}`、`{<span style="font-family:Times New Roman; font-style:italic;">n</span>,}`、`{<span style="font-family:Times New Roman; font-style:italic;">n</span>,<span style="font-family:Times New Roman; font-style:italic;">m</span>}`

低｜`^`、`$`、中介字符

次最低｜串接，即相鄰字符連接在一起

最低｜`|`

## 範例

- 以下使用PHP語言
- 驗證字串是否只含數字與英文，字串長度並在4~16個字元之間：

```php
<?php
$str = 'a1234';
if (preg_match("/^[a-zA-Z0-9]{4,16}$/", $str)) {
    echo "CONFIRM";
} else {
    echo "FAILED";
}
?>
```

```php
<?php
$str = 'a1234';
if (preg_match("/^[A-Za-z][1289]\d{8}$/", $str)) {
    echo "CONFIRM";
} else {
    echo "FAILED";
}
?>
```

- 以下使用Perl語言
- 驗證字串是否只含數字與英文，字串長度並在4~16個字元之間：

```perl
print $str = "a1234" =~ m:^[a-zA-Z0-9]{4,16}$: ? "CONFIRM" : "FAILED";
```

```perl
print $str = "a1234" =~ m"^\w[1289]\d{8}$" ? "CONFIRM" : "INVALID";
```

- 以下使用python語言

```python3
import re
s=' 192.137.1.336  192.168.1.137.123  192.168.1.138 '
print(re.findall(r'(?<![\.\d])(?:25[0-5]\.|2[0-4]\d\.|[01]?\d\d?\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?![\.\d])',s))
```

## 外部連結

- 各種語言或工具軟體的不同風格的正則表達式文法規定
- 正則表達式30分鐘入門教程
- 正則表達式應用範例
- 正規化表示法-ProgWiki
- Regexper
- RegExr: Learn, Build, & Test RegEx ——公式上的懸浮氣泡UI解釋該規則匹配的字串；匹配結果有對應的解釋；右側邊欄有正則表達式的詳細規範及圖中的小抄
- regex101.com ——查看匹配資訊，並且會用不同的顏色將 Group 標記出來。
- Debuggex: Online visual regex tester. JavaScript, Python, and PCRE. ——另一個正則表達式的網頁在線調試/驗證器，用狀態機圖解輸入的正則表達式的語義，並可檢測輸入的測試字串是否匹配該正則表達式