热门问题
时间线
聊天
视角
正則表達式
形成搜索模式的字符序列 来自维基百科,自由的百科全书
Remove ads
正則表達式(英語:regular expression,常簡寫為regex、regexp或RE),又稱規律表達式、正規表達式、正規表示法、規則運算式、常規表示法,是計算機科學概念,用簡單字串來描述、匹配文中全部符合指定格式的字串,現在很多文本編輯器都支援用正則表達式搜尋、取代符合指定格式的字串。
![]() | 此條目內容疑欠準確,有待查證。 (2013年11月22日) |
此條目需要補充更多來源。 (2013年11月22日) |
許多程序設計語言都支援用正則表達式操作字串,如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的設計中已考慮到了這點。
Remove ads
理論
正則表達式可以用形式化語言理論的方式來表達。正則表達式由常量和算子組成,它們分別表示字符串的集合和在這些集合上的運算。給定有限字母表Σ定義了下列常量:
定義了下列運算:
- 串接 表示集合,這裡的表示將和兩個字符串按順序連接。例如:。
- 選擇 表示和的併集。例如:。
- 克萊尼(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星號和併集明顯是需要的,但是我們或許可以限制它們的使用。由於正則表達式如此簡單,沒有辦法在語法上把它重寫成某種規範形式。過去公理化的缺乏導致了星號高度問題。最近Dexter Kozen用克萊尼代數公理化了正則表達式。[來源請求]
很多現實世界的「正則表達式」引擎實現了不能用正則表達式代數表達的特徵。[來源請求]
Remove ads
基本語法
一個正則表達式通常被稱為一個模式(pattern),為用來描述或者匹配一系列符合某個句法規則的字符串。例如:Handel、Händel和Haendel這三個字符串,都可以由H(a|ä|ae)ndel
這個模式來描述。大部分正則表達式的形式都有如下的結構:
某個字符後的數量限定符用來限定前面這個字符允許出現的個數。最常見的數量限定符包括+
、?
和*
(不加數量限定則代表出現一次且僅出現一次):
- 圓括號
()
可以用來定義操作符的範圍和優先度。例如,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的子集):
Remove ads
Unicode處理
在.NET、Java、JavaScript、Python的正則表達式中,可以用\uXXXX
表示一個Unicode字符,其中XXXX
為四位16進制數字。
Unicode字符的三種性質:[5]
- 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{P}
- 其它符號
\p{C}
(包括不可見控制字符與未用碼位)
- 字符
- 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字符組
Remove ads
優先權
範例
- 以下使用PHP語言
- 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
<?php $str = 'a1234'; if (preg_match("/^[a-zA-Z0-9]{4,16}$/", $str)) { echo "CONFIRM"; } else { echo "FAILED"; } ?>
- 簡易的中華民國國民身分證字號驗證:
<?php $str = 'a1234'; if (preg_match("/^[A-Za-z][1289]\d{8}$/", $str)) { echo "CONFIRM"; } else { echo "FAILED"; } ?>
- 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
- 以下使用Perl語言
- 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
print $str = "a1234" =~ m:^[a-zA-Z0-9]{4,16}$: ? "CONFIRM" : "FAILED";
- 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
- 簡易的中華民國身份證字號驗證:
print $str = "a1234" =~ m"^\w[1289]\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'(?<![\.\d])(?:25[0-5]\.|2[0-4]\d\.|[01]?\d\d?\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?![\.\d])',s))
- 使用正則表示式匹配ip地址:
相關條目
- 正則表達式引擎對比
- 擴展巴科斯範式
- Thompson構造法
注釋
參考文獻
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads