正則表達式(Regular Expression,RegExp,regex)使用單個字符串來描述和匹配一系列符合某種句法規則的字符串。此概念來自形式化語言理論,最初由貝爾實驗室實現。正則表達式最初在 Perl 中實現,它的推廣得益於 UNIX 軟件的流行,尤爲是 SED,GREP 等。 如今許多編程語言都內置了正則表達式引擎,如 PERL、Python、JavaScript、Java、C++ 等。不少文本編輯器也支持正則表達式來進行檢索和替換,如 Vim、Sublime Text、Visual Studio Code 等。正則表達式相關的學習文章網上也是一大推,本文主要記錄正則表達式的入門教程和經常使用公式工具,方便你們活學活用。html
正則表達式從小白到入門
2019年09月12日 - 初稿python
閱讀原文 - https://wsgzao.github.io/post...git
擴展閱讀github
正則表達式 30 分鐘入門教程 - https://deerchao.net/tutorial...web
爲何須要正則表達式 - 王垠正則表達式
學習 Unix 最開頭,你們都學過正則表達式 (regexp)。但是有沒有人考慮過咱們爲何須要正則表達式?express
正則表達式原本的初衷是用來從無結構的字符串中提取信息,卻不知這正好是 Unix 的缺陷所在。Unix 用無結構的字符串來表示數據,致使了諸多複雜的基於 regexp 的軟件的誕生。sed, AWK, Perl, … 都是爲了一樣的目的來到這個世界上的。若是不是由於 Unix 用字符串來表示數據,咱們就會擁有按數據結構類型的直接存儲,而不須要折騰 regexp。正則表達式有它本身的價值(針對天然語言),可是咱們其實不須要把它應用到程序語言和操做系統裏面。編程
正則表達式自己用一個字符串來表示,這帶來另一些問題。由於正則表達式的本質不是字符串,而是一個數據結構。學過計算理論的人可能知道這個數據結構叫作 NFA(nondeterministic finite automaton,非肯定性有限自動機)。全部的數據結構應該由程序語言自己來表示,就像用 Java 構造一個對象用 new ClassA("a")
同樣。可是正則表達式強迫你把這個簡單的構造函數調用寫成一個字符串。因此在這個比方之下,你得寫成 new ClassA(\"a\")
。這樣當你想要組合這些表達式的時候就發現,正則表達式幾乎都是不可組合 (compose) 的。你幾乎不可能不能把兩個 regexp 的變量 A 和 B 安全拼接成一個,好比用 Java 的字符串拼接 A+B。由於你不知道這兩個字符串拼在一塊兒以後,那些稀奇古怪的符號會出現什麼交叉反應,使得最後的識別的東西根本不是你想要的。安全
在正則表達式中,因爲正則表達式自己的構造函數與數據自己合併到一塊兒,咱們不得不對某些 「特殊字符」 進行 escape。這些特殊字符,實際上是用來描述 NFA 的記號,它們屬於更高一層的語言。但是在正則表達式裏,它們與 NFA 節點裏的字符混爲一談。好比很簡單的一個 block comment 的正則表達式,卻要寫成這個樣子:數據結構
/\\\\\*(\[^\\\\\*\]|\[^/\])\*\\\\\*/
顯然這樣的表達式很容易出錯。 若是咱們用程序語言的表達式來構造這個表達式,它應該是這樣:
(@... "/\*" (@\*(@!"\*/")) "\*/")
在這個我本身設計的 Scheme 表達式裏,以 @
開頭的標識符都是構造函數。其中 @...
是構造 sequence,@*
是構造一個 zero-or-more 的匹配,@!
構造一個否認匹配。這個表達式是說:「以 / *
開頭,接着零個或者多個不是 * /
的字符,最後接着一個 * /
。這樣一來清晰明瞭,什麼表達式在什麼 「層次」 都很清楚,不須要什麼反斜槓 escape,並且這樣的表達式能夠 compose。好比:
(define reg1 (@... "/\*" (@\*(@!"\*/")) "\*/")) (define reg2 (@+ "foo")) (define reg3 (@= "b"))
定義這三個表達式以後,咱們以後能夠用像 (@... reg1 (@or reg2 reg3))
這樣的表達式來鏈接 3 個不一樣的表達式,構造出更大的表達式。這樣的構造能夠無限的擴展。從這裏以及以往的經驗,我總結出一個廣泛適用的程序設計的教訓:儘可能不要把多個層次的語言 「壓縮」 到一層。咱們也看到正則表達式與 「Unix 哲學」 有很大關係。我沒有考古,因此不知道孰先孰後,可是它們確定有直接的因果關係。二者都是 Unix 複雜性的來源。
再來看取自 12306 網站的一段代碼
// http://www.12306.cn/mormhweb/js/adKyfw.min.js d = d.replace("'", ""); d = d.replace("%", ""); d = d.replace("#", ""); d = d.replace("&", ""); d = d.replace("*", ""); d = d.replace("(", ""); d = d.replace(")", ""); d = d.replace("@", ""); d = d.replace("`", ""); d = d.replace("/", ""); d = d.replace("\\", ""); d = d.replace(",", ""); d = d.replace(".", ""); d = d.replace("=", ""); d = d.replace("<", ""); d = d.replace(">", "");
上述代碼是在過濾掉不合法的搜索字符(姑且不論客戶端過濾是否安全), 咱們能夠用一行正則替換來實現相同的功能:
d = d.replace(/'%#\&\*\(\)@`\/\\,\.=<>/g, '');
感謝做者deerchao從2006年開始更新至今,謝謝
定義正則表達式的方式在不一樣的工具中可能有所差異,但正則表達式內容的語法是一致的。 正則表達式有三類語法結構:
harttle
只能匹配 harttle
, 不可匹配 hart
。|
)。例如:harttle|serene
能夠匹配 harttle
或者 serene
。 選擇的優先級級低於串接,所以不少狀況下均可以省略括號。+
, ?
, *
,分別表示左側的字符出現一次或更多,不出現或出現一次,不出現或出現任意次。例如 harttle?
能夠匹配 harttl
和 harttle
。()
)。組合用來定義操做符的做用範圍和優先級。例如 har(ttle)?
能夠匹配 harttle
和 har
,h(a|u)rttle
能夠匹配 harttle
和 hurttle
。字符 | 描述 |
---|---|
\\ |
將下一個字符標記爲一個特殊字符、或一個原義字符、或一個向後引用、或一個八進制轉義符。例如,」n 「匹配字符」n 「。」\n 「匹配一個換行符。序列」\ 「匹配」\ 「而」 ( 「則匹配」( 「。 |
^ |
匹配輸入字符串的開始位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 也匹配」\n 「或」\r 「以後的位置。 |
$ |
匹配輸入字符串的結束位置。若是設置了 RegExp 對象的 Multiline 屬性,$ 也匹配」\n 「或」\r 「以前的位置。 |
* |
匹配前面的子表達式零次或屢次。例如,zo 能匹配」z 「、」zo 「以及」zoo 「。等價於 {0,}。 |
+ |
匹配前面的子表達式一次或屢次。例如,」zo+ 「能匹配」zo 「以及」zoo 「,但不能匹配」z 「。+ 等價於 {1,}。 |
? |
匹配前面的子表達式零次或一次。例如,」do(es)? 「能夠匹配」do 「或」does 「中的」do 「。? 等價於 {0,1}。 |
{n} |
n 是一個非負整數。匹配肯定的 n 次。例如,」o{2} 「不能匹配」Bob 「中的」o 「,可是能匹配」food 「中的兩個 o。 |
{n,} |
n 是一個非負整數。至少匹配 n 次。例如,」o{2,} 「不能匹配」Bob 「中的」o 「,但能匹配」foooood 「中的全部 o。」o{1,} 「等價於」 o+ 「。」o{0,} 「則等價於」o 「。 |
{n,m} |
m 和 n 均爲非負整數,其中 n<=m。最少匹配 n 次且最多匹配 m 次。例如,」o{1,3} 「將匹配」fooooood 「中的前三個 o。」o{0,1} 「等價於」o? 「。請注意在逗號和兩個數之間不能有空格。 |
? |
當該字符緊跟在任何一個其餘限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串」oooo 「,」o+? 「將匹配單個」o 「,而」 o+ 「將匹配全部」o 「。 |
. |
匹配除」\n 「以外的任何單個字符。要匹配包括」\n 「在內的任何字符,請使用像」 (.|n) 「的模式。 |
(pattern) |
匹配 pattern 並獲取這一匹配的子字符串。該子字符串用於向後引用。所獲取的匹配能夠從產生的 Matches 集合獲得,在 VBScript 中使用 SubMatches 集合,在 JScript 中則使用 $0...$9 屬性。要匹配圓括號字符,請使用」( 「或」) 「。 |
(?:pattern) |
匹配 pattern 但不獲取匹配的子字符串,也就是說這是一個非獲取匹配,不存儲匹配的子字符串用於向後引用。這在使用或字符」(|) 「來組合一個模式的各個部分是頗有用。例如」industr(?:y|ies) 「就是一個比」industry|industries 「更簡略的表達式。 |
(?=pattern) |
正向確定預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如,」Windows(?=95|98|NT|2000) 「能匹配」Windows2000 「中的」Windows 「,但不能匹配」 Windows3.1 「中的」Windows 「。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。 |
(?!pattern) |
正向否認預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如」Windows(?!95|98|NT|2000) 「能匹配」Windows3.1 「中的」Windows 「,但不能匹配」 Windows2000 「中的」Windows 「。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始 |
(?<=pattern) |
反向確定預查,與正向確定預查相似,只是方向相反。例如,」(?<=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] |
排除型(negate)字符集合。匹配未列出的任意字符。例如,」[^abc] 「能夠匹配」plain 「中的」plin 「。 |
[a-z] |
字符範圍。匹配指定範圍內的任意字符。例如,」[a-z] 「能夠匹配」a 「到」z 「範圍內的任意小寫字母字符。 |
[^a-z] |
排除型的字符範圍。匹配任何不在指定範圍內的任意字符。例如,」[^a-z] 「能夠匹配任何不在」a 「到」z 「範圍內的任意字符。 |
\b |
匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,」er\b 「能夠匹配」never 「中的」er 「,但不能匹配」verb 「中的」er 「。 |
\B |
匹配非單詞邊界。」er\B 「能匹配」verb 「中的」er 「,但不能匹配」never 「中的」er 「。 |
\cx |
匹配由 x 指明的控制字符。例如,\cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。不然,將 c 視爲一個原義的」c 「字符。 |
\d |
匹配一個數字字符。等價於 [0-9] 。 |
\D |
匹配一個非數字字符。等價於 [^0-9] 。 |
\f |
匹配一個換頁符。等價於 \x0c 和 \cL 。 |
\n |
匹配一個換行符。等價於 \x0a 和 \cJ 。 |
\r |
匹配一個回車符。等價於 \x0d 和 \cM 。 |
\s |
匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v] 。 |
\S |
匹配任何非空白字符。等價於 [^ \f\n\r\t\v] 。 |
\t |
匹配一個製表符。等價於 \x09 和 \cI 。 |
\v |
匹配一個垂直製表符。等價於 \x0b 和 \cK 。 |
\w |
匹配包括下劃線的任何單詞字符。等價於」[A-Za-z0-9] 「。 |
\W |
匹配任何非單詞字符。等價於」[^A-Za-z0-9] 「。 |
\xn |
匹配 n,其中 n 爲十六進制轉義值。十六進制轉義值必須爲肯定的兩個數字長。例如,」\x41 「匹配」A 「。」\x041 「則等價於」\x04&1 「。正則表達式中可使用 ASCII 編碼。. |
\num |
向後引用(back-reference)一個子字符串(substring),該子字符串與正則表達式的第 num 個用括號圍起來的子表達式(subexpression)匹配。其中 num 是從 1 開始的正整數,其上限多是 99。例如:」(.)\1 「匹配兩個連續的相同字符。 |
\n |
標識一個八進制轉義值或一個向後引用。若是 \n 以前至少 n 個獲取的子表達式,則 n 爲向後引用。不然,若是 n 爲八進制數字(0-7),則 n 爲一個八進制轉義值。 |
\nm |
標識一個八進制轉義值或一個向後引用。若是 \nm 以前至少有 nm 個得到子表達式,則 nm 爲向後引用。若是 \nm 以前至少有 n 個獲取,則 n 爲一個後跟文字 m 的向後引用。若是前面的條件都不知足,若 n 和 m 均爲八進制數字(0-7),則 \nm 將匹配八進制轉義值 nm。 |
\nml |
若是 n 爲八進制數字(0-3),且 m 和 l 均爲八進制數字(0-7),則匹配八進制轉義值 nml。 |
\un |
匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如,\u00A9 匹配版權符號(©)。 |