正則表達式

正則表達式（regular expression，常簡寫為regex、regexp或RE），又稱規律表達式、正規-{zh-cn:表示式; zh-tw:表達式; zh-hk:表示式;}-、正規表示法、規則運算式、常規表示法，是計算機科學概念，用簡單字串來描述、匹配文中全部符合指定格式的字串，現在很多文本編輯器都支援用正則表達式搜尋、取代符合指定格式的字串。
許多程序設計語言都支援用正則表達式操作字串，如Perl就內建功能強大的正則表達式引擎。正則表達式這概念最初由Unix的工具軟件（例如sed和grep）普及開。

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

**歷史**
最初的正則表達式出現於理論計算機科學的自動控制理論和形式化語言理論中。在這些領域中有對計算（自動控制）的模型和對形式化語言描述與分類的研究。
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，元字符不用轉譯。
的正則表達式源自於Henry Spencer於1986年1月19日發佈的regex，它已經演化成了PCRE（Perl兼容正則表達式，Perl Compatible Regular Expressions），一個由Philip Hazel開發的，為很多現代工具所使用的庫。
各編程語言之間關於正則表達式的整合，目前開發進展得很差。Perl6的子項目Apocalypse的設計中已考慮到了這點。

**理論**
正則表達式可以用形式化語言理論的方式來表達。正則表達式由常量和算子組成，它們分別表示字符串的集合和在這些集合上的運算。給定有限字母表Σ定義了下列常量：- 空集表示集合。- 空串表示僅包含一個“不含任何字符、長度為0的字符串”的集合。- 文字字符表示僅包含一個元素的集合。
定義了下列運算：- 串接 表示集合，這裡的表示將和兩個字符串按順序連接。例如：。- 選擇 表示和的並集。例如：。- 克萊尼(Kleene)星號 表示包含且在字符串串接運算下閉合的的最小超集。這是可以通過中零或有限個字符串的串接得到所有字符串的集合。例如：。
上述常量和算子形成了克萊尼代數。
很多課本使用對選擇使用符號、或替代豎線。
為了避免括號，假定Kleene星號有最高優先級，接著是串接，接著是並集。如果沒有歧義則可以省略括號。例如：(ab)c可以寫為abc，而a|(b(c*))可以寫為a|bc*。
例子：- a|b*表示。- (a|b)*表示包括空串和任意數目個a或b字符組成的所有字符串的集合：。- ab*(c|ε)表示開始於一個a接著零或多個b和最後一個可選的c組成的字符串的集合：。
為了使表達式更簡潔，正則表達式也定義了?和+；aa*等於a+，表示a出現至少一次；而(a|ε)等於a?，表示a出現1次或不出現。有的定義中增加了補算子；表示在上但不在中的所有字符串的集合。補算子在理論上並非必要，因為它可以使用其他算子來表達，但它可以使一些表達式變得更加簡潔。
這種意義上的正則表達式可以表達正則語言，是可被有限狀態自動機精確接受的語言類。但是在簡潔性上有重要區別。某類正則語言只能用大小指數增長的自動機來描述，而要求的正則表達式的長度只線性的增長。
正則表達式對應於喬姆斯基層級的類型-3文法。但通常編程語言或其相關庫（例如PCRE）中實現的正則表達式的表達能力是喬姆斯基層級中類型-3文法的超集。在另一方面，在正則表達式和不導致這種大小上的爆炸的非確定有限狀態自動機（NFA）之間有簡單的映射；為此NFA經常被用作正則表達式的替表示式。
這種形式化中存在著冗餘，典型的體現是存在不同的正則表達式可以表達同樣的語言。有可能對兩個給定正則表達式寫一個算法來判定它們所描述的語言是否本質上相等，即簡約每個表達式到極小確定有限自動機，確定它們是否同構（等價）。這種冗餘可以消減到什麼程度？我們可以找到仍有完全表達力的正則表達式的有趣的子集嗎？這提出了一個令人驚奇的困難問題。Kleene星號和並集明顯是需要的，但是我們或許可以限制它們的使用。由於正則表達式如此簡單，沒有辦法在語法上把它重寫成某種規範形式。過去公理化的缺乏導致了Star height problem。最近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表達式全集**
正則表達式有多種不同的風格。下表是在Perl_Compatible_Regular_Expressions中元字符及其在正則表達式上下文中的行為的一個完整列表，適用於Perl或者Python編程語言（grep或者egrep的正則表達式文法是PCRE的子集）：

**Unicode處理**
在.NET、Java、JavaScript、Python的正則表達式中，可以用\uXXXX表示一個Unicode字符，其中XXXX為四位16進制數字。
字符的三種性質：- 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字符組**
~- 
\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

**優先權**

**範例**
以下使用PHP語言- 驗證字串是否只含數字與英文，字串長度並在4~16個字元之間：- 簡易的中華民國國民身分證字號驗證：
*以下使用Perl語言- 驗證字串是否只含數字與英文，字串長度並在4~16個字元之間：
print $str = "a1234" =~ m:^a-zA-Z0-9{4,16}$: ? "CONFIRM" : "FAILED";- 簡易的中華民國身份證字號驗證：
print $str = "a1234" =~ m"^\w1289\d{8}$" ? "CONFIRM" : "INVALID";
*以下使用python語言
*使用正則表示式匹配ip地址：
import re
s=' 192.137.1.336  192.168.1.137.123  192.168.1.138 '
print(re.findall(r'(?

**相關條目**
 正則表達式引擎對比- 擴展巴科斯範式- Thompson構造法

**註釋**

**參考文獻**

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