55分鐘學會正則表達式

55分鐘學會正則表達式

講的不錯,感謝做者,轉自:http://blog.jobbole.com/63398/ 程序員

正則表達式是一種查找以及字符串替換操做。正則表達式在文本編輯器中普遍使用,好比正則表達式被用於:正則表達式

  • 檢查文本中是否含有指定的特徵詞
  • 找出文中匹配特徵詞的位置
  • 從文本中提取信息,好比:字符串的子串
  • 修改文本

與文本編輯器類似,幾乎全部的高級編程語言都支持正則表達式。在這樣的語境下,「文本」也就是一個字符串,能夠執行的操做都是相似的。一些編程語言(好比Perl,JavaScript)會檢查正則表達式的語法。編程

正則表達式是什麼?編程語言

正則表達式只是一個字符串。沒有長度限制,可是,這樣的正則表達式長度每每較短。以下所示是一些正則表達式的例子:編輯器

  • I had a \S+ day today
  • [A-Za-z0-9\-_]{3,16}
  • \d\d\d\d-\d\d-\d\d
  • v(\d+)(\.\d+)*
  • TotalMessages="(.*?)"
  • <[^<>]>
這些字符串實際上都是微型計算機程序。正則表達式的語法,其實是一種輕量級、簡潔、適用於特定領域的編程語言。記住這一點,那麼你就很容易理解下面的事情:
  • 每個正則表達式,均可以分解爲一個指令序列,好比「先找到這樣的字符,再找到那樣的字符,再從中找到一個字符。。。」
  • 每個正則表達式都有輸入(文本)和輸出(匹配規則的輸出,有時是修改後的文本)
  • 正則表達式有可能出現語法錯誤——不是全部的字符串都是正則表達式
  • 正則表達式語法頗有個性,也能夠說很恐怖
  • 有時能夠經過編譯,使得正則表達式執行更快

在實現中,正則表達式還有其餘的特色。本文將重點討論正則表達式的核心語法,在幾乎全部的正則表達式中均可以見到這些規則。函數

特別提示:正則表達式與文件通配語法無關,好比 *.xml網站

正則表達式的基礎語法

字符 

正則表達式中包含了一系列的字符,這些字符只能匹配它們自己。有一些被稱爲「元字符」的特殊字符,能夠匹配一些特殊規則。ui

以下所示的例子中,我用紅色標出了元字符。this

  • I had a \S+ day today
  • [A-Za-z0-9\-_]{3,16}
  • \d\d\d\d-\d\d-\d\d
  • v(\d+)(\.\d+)*
  • TotalMessages="(.*?)"
  • <[^<>]*> 

大部分的字符,包括全部的字母和數字字符,是普通字符。也就意味着,它們只能匹配它們本身,以下所示的正則表達式:spa

cat

意味着,只能匹配一個字符串,以「c」開頭,而後是字符「a」,緊跟着是字符「t」的字符串。

到目前爲止,正則表達式的功能相似於

  • 常規的Find功能
  • Java中的 String.indexOf() 函數
  • PHP中的 strpos()函數
  • 等等
注意:不作特殊說明,正則表達式中是區分大小寫的。可是,幾乎全部正則表達式的實現,都會提供一個Flag用來控制是否區分大小寫。

 

點「.」

咱們第一個要講解的元字符是「.」。這個符號意味着能夠匹配任意一個字符。以下所示的正則表達式:

c.t

意味着匹配「以c開頭,以後是任意一個字符,緊跟着是字母t」的字符串。

在一段文本中,這樣的正則表達式能夠用來找出catcotczt這樣的字符串,甚至能夠找出c.t這樣的組合,可是不能找到ct或者是coot這樣的字符串。

使用反斜槓「\」能夠忽略元字符,使得元字符的功能與普通字符同樣。因此,正則表達式

c\.t

表示「找到字母c,而後是一個句號(「.」),緊跟着字母t」

反斜槓自己也是一個元字符,這意味着反斜槓自己也能夠經過類似的方法變回到普通字符的用途。所以,正則表達式

c\\t

表示匹配「以字符c開頭,而後是一個反斜槓,緊跟着是字母t」的字符串。

注意!在正則表達式的實現中,.是不能用於匹配換行符的。」換行符「的表示方法在不一樣實現中也不一樣。實際編程時,請參考相關文檔。在本文中,我認爲.是能夠匹配任意字符的。實現環境一般會提供一個Flag標誌位,來控制這一點。

字符類

字符類是一組在方括號內的字符,表示能夠匹配其中的任何一個字符。

  • 正則表達式c[aeiou]t,表示能夠匹配的字符串是」以c開頭,接着是aeiou中的任何一個字符,最後以t結尾」。在文本的實際應用中,這樣的正則表達式能夠匹配:cat,cet,cit,cot,cut五種字符串。
  • 正則表達式[0123456789]表示匹配任意一個整數。
  • 正則表達式[a]表示匹配單字符a。

包含忽略字符的例子

  •  

    a

     

    表示匹配字符串[a]
  • [\[\]\ab]表示匹配的字符爲」["或者'']」或者」a」,或者」b」
  • [\\\[\]]表示匹配的字符爲」\」或者 「[」或者"]「

在字符類中,字符的重複和出現順序並不重要。[dabaaabcc]與[abc]是相同的

重要提示:字符類中和字符類外的規則有時不一樣,一些字符在字符類中是元字符,在字符類外是普通字符。一些字符正好相反。還有一些字符在字符類中和字符類外都是元字符,這要視狀況而定!

好比,.表示匹配任意一個字符,而[.]表示匹配一個全角句號。這不是一回事!

字符類的範圍

在字符集中,你能夠經過使用短橫線來表示匹配字母或數字的範圍。

  • [b-f]與[b,c,d,e,f]相同,都是匹配一個字符」b」或」c」或」d」或」e」或」f」
  • [A-Z]與[ABCDEFGHIJKLMNOPQRSTUVWXYZ]相同,都是匹配任意一個大寫字母。
  • [1-9]與[123456789]相同,都是匹配任意一個非零數字。

練習

使用目前咱們已經講解的正則表達式相關知識,在字典中匹配找到含有最多連續元音的單詞,同時找到含有最多連續輔音的單詞。

答案

[aeiou][aeiou][aeiou][aeiou][aeiou][aeiou] 這樣的正則表達式,能夠匹配連續含有六個元音的單詞,好比 euouae 和 euouaes

一樣的,恐怖的正則表達式[bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz] 能夠找到連續含有十個輔音的單詞sulphhydryls

下文中,咱們會講解,怎樣有效縮短這樣的正則表達式長度。

在字符類以外,短橫線沒有特殊含義。正則表達式a-z,表示匹配字符串「以a開頭,而後是一個短橫線,以z結尾」。

範圍和單獨的字符可能在一個字符類中同時出現:

  • [0-9.,]代表匹配一個數字,或者一個全角句號,或者一個逗號
  • [0-9a-fA-F]意味着匹配一個十六進制數
  • [a-zA-Z0-9\-]意味着匹配一個字母、數字或者一個短橫線

練習

使用已經介紹過的正則表達式知識,匹配YYYY-MM-DD格式的日期。

答案

[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

一樣的,下文中,咱們會介紹怎樣有效減小這樣的正則表達式長度。

雖然你能夠嘗試在正則表達式中使用一些非字母或數字做爲範圍的最後一個符號,好比abc[!-/]def,可是這並非在每種實現中都合法。即便這樣的語法是合法的,這樣的語義也是模糊的。最好不要這樣使用。

同時,你必須謹慎選擇範圍的邊界值。即便[A-z]在你使用的實現中,是合法的,也可能會產生沒法預料的運行結果。(注意,在z到a之間,是有字符存在的)

注意:範圍的字符值表明的是字符而已,並不能表明數值範圍,好比[1-31]表示匹配一個數字,是1或者2或者3,而不是匹配一個數值在1到31之間的數。

字符類的反義

你能夠在字符類的起始位放一個反義符。

  • [^a]表示匹配任何不是「a」的字符
  • [^a-zA-Z0-9]表示匹配任何不是字母也不是數字的字符
  • [\^abc]匹配一個爲「^」或者a或者b或者c的字符
  • [^\^]表示匹配任何不爲「^」的字符

練習

在字典中,找到一個不知足「在e以前有i,可是沒有c」的例子。

答案

cie和[^c]ei都要能夠找到不少這樣的例子,好比ancient,science,viel,weigh

 

轉義字符類

\d這個正則表達式與[0-9]做用相同,都是匹配任何一個數字。(要匹配\d,應該使用正則表達式\\d)

\w與[0-9A-Za-z]相同,都表示匹配一個數字或字母字符

\s意味着匹配一個空字符(空格,製表符,回車或者換行)

另外

  • \D與[^0-9]相同,表示匹配一個非數字字符。
  • \W與[^0-9A-Za-z]相同,表示匹配一個非數字同時不是字母的字符。
  • \S表示匹配一個非空字符。

這些是你必須掌握的字符。你可能已經注意到了,一個全角句號「.」也是一個字符類,能夠匹配任意一個字符。

不少正則表達式的實現中,提供了更多的字符類,或者是標誌位在ASCII碼的基礎上,擴展示有的字符類。

特別提示:統一字符集中包含除了0至9以外的更多數字字符,一樣的,也包含更多的空字符和字母字符。實際使用正則表達式時,請仔細查看相關文檔。

練習

簡化正則表達式 [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

答案

\d\d\d\d-\d\d-\d\d.

 

重複

在字符或字符集以後,你可使用{ }大括號來表示重複

  • 正則表達式a{1}與a意思相同,都表示匹配字母a
  • a{3}表示匹配字符串「aaa」
  • a{0}表示匹配空字符串。從這個正則表達式自己來看,它毫無心義。若是你對任何文本執行這樣的正則表達式,你能夠定位到搜索的起始位置,即便文本爲空。
  • a\{2\}表示匹配字符串「a{2}」
  • 在字符類中,大括號沒有特殊含義。[{}]表示匹配一個左邊的大括號,或者一個右邊的大括號

練習

簡化下面的正則表達式

  • z.......z
  • \d\d\d\d-\d\d-\d\d
  • [aeiou][aeiou][aeiou][aeiou][aeiou][aeiou]
  • [bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz]

答案

  • z.{7}z
  • \d{4}-\d{2}-\d{2}
  • [aeiou]{6}
  • [bcdfghjklmnpqrstvwxyz]{10}

注意:重複字符是沒有記憶性的,好比[abc]{2}表示先匹配」a或者b或者c」,再匹配」a或者b或者c」,與匹配」aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc「同樣。[abc]{2}並不能表示匹配」aa或者bb或者cc「

 

指定重複次數範圍

重複次數是能夠指定範圍的

  • x{4,4}與x{4}相同
  • colou{0,1}r表示匹配colour或者color
  • a{3,5}表示匹配aaaaa或者aaaa或者aaa

注意這樣的正則表達式會優先匹配最長字符串,好比輸入 I had an aaaaawful day會匹配單詞aaaaawful中的aaaaa,而不會匹配其中的aaa。

重複次數是能夠有範圍的,可是有時候這樣的方法也不能找到最佳答案。若是你的輸入文本是I had an aaawful daaaaay那麼在第一次匹配時,只能找到aaawful,只有再次執行匹配時才能找到daaaaay中的aaaaa.

重複次數的範圍能夠是開區間

  • a{1,}表示匹配一個或一個以上的連續字符a。依然是匹配最長字符串。當找到第一個a以後,正則表達式會嘗試匹配儘可能多個的連續字母a。
  • .{0,}表示匹配任意內容。不管你輸入的文本是什麼,即便是一個空字符串,這個正則表達式都會成功匹配全文並返回結果。

練習

使用正則表達式找到雙引號。要求輸入字符串可能包含任意個字符。

調整你的正則表達式使得在一對雙引號中間再也不包含其餘的雙引號。

答案

 ".{0,}", 而後 "[^"]{0,}".

 

關於重複的轉義字符

?與{0,1}相同,好比,colou?r表示匹配colour或者color

*與{0,}相同。好比,.*表示匹配任意內容

+與{1,}相同。好比,\w+表示匹配一個詞。其中」一個詞」表示由一個或一個以上的字符組成的字符串,好比_var或者AccountName1.

這些是你必須知道的經常使用轉義字符,除此以外還有:

  • \?\*\+ 表示匹配字符串」?*+」
  • [?*+]表示匹配一個問號,或者一個*號,或者一個加號

練習

簡化下列的正則表達式:

  • ".{0,}" and "[^"]{0,}"
  • x?x?x?
  • y*y*
  • z+z+z+z+

答案

  • ".*" and "[^"]*"
  • x{0,3}
  • y*
  • z{4,}

 

練習

寫出正則表達式,尋找由非字母字符分隔的兩個單詞。若是是三個呢?六個呢?

\w+\W+\w+\w+\W+\w+\W+\w+\w+\W+\w+\W+\w+\W+\w+\W+\w+\W+\w+.

下文中,咱們將簡化這個正則表達式。

 

 非貪婪匹配

正則表達式 「.*」 表示匹配雙引號,以後是任意內容,以後再匹配一個雙引號。注意,其中匹配任意內容也能夠是雙引號。一般狀況下,這並非頗有用。經過在句尾加上一個問號,可使得字符串重複再也不匹配最長字符。

  • \d{4,5}?表示匹配\d\d\d\d或者\d\d\d\d\d。也就是和\d{4}同樣
  • colou??r與colou{0,1}r相同,表示找到color或者colour。這與colou?r同樣。
  • 「.*?」表示先匹配一個雙引號,而後匹配最少的字符,而後是一個雙引號,與上面兩個例子不一樣,這頗有用。

選擇匹配

你可使用|來分隔能夠匹配的不一樣選擇:

  • cat|dog表示匹配」cat」或者」dog」
  • red|blue|以及red||blue以及|red|blue都表示匹配red或者blue或者一個空字符串
  • a|b|c與[abc]相同
  • cat|dog|\|表示匹配」cat」或者」dog」或者一個分隔符」|「
  • [cat|dog]表示匹配a或者c或者d或者g或者o或者t或者一個分隔符「|」

練習

簡化下列正則表達式:

  • s|t|u|v|w
  • aa|ab|ba|bb
  • [abc]|[^abc]
  • [^ab]|[^bc]
  • [ab][ab][ab]?[ab]?

答案

  • [s-w]
  • [ab]{2}
  • .
  • [^b]
  • [ab]{2,4}

練習

使用正則表達式匹配1到31之間的整數,[1-31]不是正確答案!

這樣的正則表達式不惟一. [1-9]|[12][0-9]|3[01] 是其中之一。

 

分組

你可使用括號表示分組:

  • 經過使用 Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day 匹配一週中的某一天
  • (\w*)ility  與 \w*ility 相同。都是匹配一個由」ility」結尾的單詞。稍後咱們會講解,爲什麼第一種方法更加有用。
  • 表示匹配一對括號。
  • [()]表示匹配任意一個左括號或者一個右括號

練習

在《時間機器中》找到一對括號中的內容,而後經過修改正則表達式,找到不含括號的內容。

答案

.. 而後是, [()].

分組能夠包括空字符串:

  • (red|blue)表示匹配red或者blue或者是一個空字符串
  • abc()def與abcdef相同

你也能夠在分組的基礎上使用重複:

  • (red|blue)?與(red|blue|)相同
  • \w+(\s+\w+)表示匹配一個或多個由空格分隔的單詞

練習

簡化正則表達式 \w+\W+\w+\W+\w+ 以及 \w+\W+\w+\W+\w+\W+\w+\W+\w+\W+\w+.

答案

\w+(\W+\w+){2}\w+(\W+\w+){5}.

 

單詞分隔符

在單詞和非單詞之間有單詞分隔符。記住,一個單詞\w是[0-9A-Za-z_],而非單詞字符是\W(大寫),表示[^0-9A-Za-z_].

在文本的開頭和結尾一般也有單詞分隔符。

在輸入文本it’s a cat中,實際有八個單詞分隔符。若是咱們在cat以後在上一個空格,那就有九個單詞分隔符。.

  • \b表示匹配一個單詞分隔符
  • \b\w\w\w\b表示匹配一個三字母單詞
  • a\ba表示匹配兩個a中間有一個單詞分隔符。這個正則表達式永遠不會有匹配的字符,不管輸入怎樣的文本。

單詞分隔符自己並非字符。它們的寬度爲0。下列正則表達式的做用不一樣

  • (\bcat)\b
  • (\bcat\b)
  • \b(cat)\b
  • \b(cat\b)

練習

在詞典中找到最長的單詞。

答案

在嘗試以後發現,\b.{45,}\b能夠在字典中找到最長單詞

 

換行符

一篇文本中能夠有一行或多行,行與行之間由換行符分隔,好比:

  • Line一行文字
  • Line break換行符
  • Line一行文字
  • Line break換行符
  • Line break換行符
  • Line一行文字

注意,全部的文本都是以一行結束的,而不是以換行符結束。可是,任意一行均可能爲空,包括最後一行。

行的起始位置,是在換行符和下一行首字符之間的空間。考慮到單詞分隔符,文本的起始位置也能夠當作是首行位置。

最後一行是最後一行的尾字符和換行符之間的空間。考慮到單詞分隔符,文本的結束也能夠認爲是行的結束。

那麼新的格式表示以下:

  • Start-of-line, line, end-of-line
  • Line break
  • Start-of-line, line, end-of-line
  • Line break
  • Line break
  • Start-of-line, line, end-of-line

基於上述概念:

  • ^表示匹配行的開始位置
  • $表示匹配行的結束位置
  • ^&表示一個空行
  • ^.*& 表示匹配全文內容,由於行的開始符號也是一個字符,"."會匹配這個符號。找到單獨的一行,可使用 ^.*?$
  • \^\$表示匹配字符串「^$」
  • [$]表示匹配一個$。可是,[^]不是合法的正則表達式。記住在方括號中,字符有不一樣的特殊含義。要想在方括號內匹配^,必須用[\^]

與字符分隔符同樣,換行符也不是字符。它們寬度爲0.以下所示的正則表達式做用不一樣:

  • (^cat)$
  • (^cat$)
  • ^(cat)$
  • ^(cat$)

練習

使用正則表達式在《時間機器》中找到最長的一行。

答案

使用正則表達式^.{73,}$能夠匹配長度爲73的一行

 

文本分界

在不少的正則表達式實現中,將^和$做爲文本的開始符號和結束符號。

還有一些實現中,用\A和\z做爲文本的開始和結束符號。

 

捕捉和替換

從這裏開始,正則表達式真正體現出了它的強大。

捕獲組

你已經知道了使用括號能夠匹配一組符號。使用括號也能夠捕獲子串。假設正則表達式是一個小型計算機程序,那麼捕獲子串就是它輸出的一部分。

正則表達式(\w*)ility表示匹配以ility結尾的詞。第一個被捕獲的部分是由\w*控制的。好比,輸入的文本內容中有單詞accessibility,那麼首先被捕獲的部分是accessib。若是輸入的文本中有單獨的ility,則首先被捕獲的是一個空字符串。

你可能會有不少的捕獲字符串,它們可能靠得很近。捕獲組從左向右編號。也就是隻須要對左括號計數。

假設有這樣的正則表達式:(\w+) had a ((\w+) \w+)

輸入的內容是:I had a nice day 

  • 捕獲組1:I
  • 捕獲組2:nice day
  • 捕獲組3:nice

在一些正則表達式的實現中,你能夠從零開始編號,編號零表示匹配整句話:I had a nice day.

在其餘的實現中,若是沒有制定捕獲組,那麼捕獲組1會自動地填入捕獲組0的信息。

是的,這也意味着會有不少的括號。有一些正則表達式的實現中,提供了「非捕獲組」的語法,可是這樣的語法並非標準語法,所以咱們不會介紹。

從一個成功的匹配中返回的捕獲組個數,與使用原來的正則表達式得到的捕獲組個數相同。記住這一點,你能夠解釋一些奇怪的現象。.

正則表達式((cat)|dog)表示匹配cat或者dog。這裏有兩個捕獲組,若是輸入文本是dog,那麼捕獲組1是dog,捕獲組2爲空。

正則表達式a(\w)*表示匹配一個以a開頭的單詞。這裏只有一個捕獲組

  • 若是輸入文本爲a,捕獲組1爲空。
  • 若是輸入文本爲ad,捕獲組爲d
  • 若是輸入文本爲avocado,捕獲組1爲v。可是捕獲組0表示整個單詞avocado.

 

替換

假如你使用了一個正則表達式去匹配字符串,你能夠描述另一個字符串來替換其中的匹配字符。用來替換的字符串稱爲替換表達式。它的功能相似於

  • 常規的Replace會話
  • Java中的String.replace()函數
  • PHP的str_replace()函數
  • 等等

練習

將《時間機器》中全部的元音字母替換爲r。

答案

使用正則表達式[aeiou]以及[AEIOU],對應的替換字符串分別爲r,R.

可是,你能夠在替換表達式中引用捕獲組。這是在替換表達式中,你能夠惟一操做的地方。這也是很是有效的,由於這樣你就不用重構你找到的字符串。

假設你正在嘗試將美國風格的日期表示MM/DD/YY替換爲ISO 8601日期表示YYYY-MM-DD

  • 從正則表達式(\d\d)/(\d\d)/(\d\d)開始。注意,這其中有三個捕獲組:月份,日期和兩位的年份。
  • .捕獲組的內容和捕獲組編號之間用反斜槓分隔,所以你的替換表達式應該是20\3-\1-\2.
  • 若是咱們輸入的文本中包含03/04/05表示2005年3月4日那麼:
    • 捕獲組1:03
    • 捕獲組2:04
    • 捕獲組3:05
    • 替換字符串2005-03-04.

在替換表達式中,你能夠屢次使用捕獲組

  • 對於雙元音,正則表達式爲([aeiou]),替換表達式爲\l\l
  • 在替換表達式中不能使用反斜槓。好比,你在計算機程序中但願使用字符串中使用部分文本。那麼,你必須在每一個雙引號或者反斜槓以前加上反斜槓。
  • 你的正則表達式能夠是([\\"])。捕獲組1是雙引號或者反斜槓
  • 你的替換表達式應該是\\\l

在某些實現中,採用美圓符號$代替\

練習

使用正則表達式和替換表達式,將23h59這樣的時間戳轉化爲23:59.

答案

正則表達式finds the timestamps, 替換表達式\1:\2

 

反向引用

在一個正則表達式中,你也能夠引用捕獲組。這稱做:反向引用

好比,[abc]{2}表示匹配aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc.可是{[abc]}\1表示只匹配aa或者bb或者cc.

練習

在字典中,找到包含兩次重複子串的最長單詞,好比papacoco

\b(.{6,})\1\b 匹配 chiquichiqui.

若是咱們不在意單詞的完整性,咱們能夠忽略單詞的分解,使用正則表達式 (.{7,})\1匹配countercountermeasure 以及 countercountermeasures.

使用正則表達式編程

特別提醒:

過分使用的反斜槓

在一些編程語言,好比Java中,對於包含正則表達式的字符串沒有特殊標記。字符串有着本身的過濾規則,這是優先於正則表達式規則的,這是頻繁使用反斜槓的緣由。

好比在Java中

  • 匹配一個數字,使用的正則表達式從\d變爲代碼中的String re= 「\\d」
  • 匹配雙引號字符串的正則表達式從"[^"]*" 變爲String re = 「\」[^\"]*\」"
  • 匹配反斜槓或者是左邊方括號,或者右邊方括號的正則表達式從[\\\[\]] 變爲String re = 「[\\\\\

     

     

     

    ]」;
  • String re = "\\s"; 和String re = "[ \t\r\n]"; 是等價的. 注意它們實際執行調用時的層次不一樣。

在其餘的編程語言中,正則表達式是由特殊標明的,好比使用/。下面是JavaScript的例子:

  • 匹配一個數字,\d會簡單寫成 var regExp = /\d/;.
  • 匹配一個反斜槓或者一個左邊的方括號或者一個右邊的方括號, var regExp = /[\\\[\]]/;
  • var regExp = /\s/; 和 var regExp = /[ \t\r\n]/; 是等價的
  • 固然,這意味着在使用/時必須重複兩次。好比找到URL必須使用var regExp = /https?:\/\//;.

我但願如今你能明白,我爲何讓你特別注意反斜槓。

 

動態正則表達式

當你動態建立一個正則表達式的時候請特別當心。若是你使用的字符串不夠完善的花,可能會有意想不到的匹配結果。這可能致使語法錯誤,更糟糕的是,你的正則表達式語法正確,可是結果沒法預料。

錯誤的Java代碼:

String sep = System.getProperty(「file.separator」); String[] directories = filePath.split(sep);

Bug:String.split() 認爲sep是一個正則表達式。可是,在Windows中,Sep是表示匹配一個反斜槓,也就是與正則表達式」\\」相同。這個正則表達式是正確的,可是會返回一個異常:PatternSyntaxException.

任何好的編程語言都會提供一種良好的機制來跳過字符串中全部的元字符。在Java中,你能夠這樣實現:

String sep = System.getProperty(「file.separator」);

String[] directories = filePath.split(Pattern.quote(sep));

 

循環中的正則表達式

將正則表達式字符串加入反覆運行的程序中,是一種開銷很大的操做。若是你能夠在循環中避免使用正則表達式,你能夠大大提升效率。

 

其餘建議

輸入驗證

正則表達式能夠用來進行輸入驗證。可是嚴格的輸入驗證會使得用戶體驗較差。好比:
 

信用卡號

在一個網站上,我輸入了個人卡號好比 1234 5678 8765 4321 網站拒絕接收。由於它使用了正則表達式\d{16}。

正則表達式應該考慮到用戶輸入的空格和短橫線。

實際上,爲何不先過濾掉全部的非數字字符,而後再進行有效性驗證呢?這樣作,能夠先使用\D以及空的替換表達式。

練習

在不先過濾掉全部的非數字字符的狀況下,使用正則表達式驗證卡號的正確性。

答案

\D*(\d\D*){16} is one of several variations which would accomplish this.

 

名字

不要使用正則表達式來驗證姓名。實際上,即便能夠,也不要企圖驗證姓名。

程序員對名字的錯誤見解:

  • 名字中不含空格
  • 名字中沒有鏈接符號
  • 名字中只會使用ASCII碼字符
  • 名字中出現的字都在特殊字符集中
  • 名字至少要有M個字的長度
  • 名字不會超過N個字的長度
  • 人們只有一個名
  • 人們只有一箇中間名
  • 人們只有一個姓(最後三條是從英語的人名考慮)

 

電子郵件地址

不要使用正則表達式驗證郵箱地址的正確性。

首先,這樣的驗證很難是精確的。電子郵件地址是能夠用正則表達式驗證的,可是表達式會很是的長而且複雜。

短的正則表達式會致使錯誤。(你知道嗎?電子郵箱地址中會有一些註釋)

第二,即便一個電子郵件地址能夠成功匹配正則表達式,也不表明這個郵箱實際存在。郵箱的惟一驗證方法,是發送驗證郵件。

 

注意

在嚴格的應用場景中,不要使用正則表達式來解析HTML或者XML。解析HTML或者XML:

  1. 使用簡單的正則表達式不能完成
  2. 整體來講很是困難
  3. 已經有其餘的方法解決

找到一個已經有的解析庫來完成這個工做

這就是55分鐘的所有內容

總結:

  • 字符: a b c d 1 2 3 4 etc.
  • 字符類: . [abc] [a-z] \d \w \s
    • . 表明任何字符
    • \d 表示「數字」
    • \w   表示」字母」, [0-9A-Za-z_]
    • \s   表示 「空格, 製表符,回車或換行符」
    • 否認字符類: [^abc] \D \W \S
  • 重複: {4} {3,16} {1,} ? * +
    • ? 表示 「零次或一次」
    • * 表示 「大於零次」
    • + 表示 「一次或一次以上」
    • 若是不加上?,全部的重複都是最長匹配的(貪婪)
  • 分組: (Septem|Octo|Novem|Decem)ber
  • 詞,行以及文本的分隔: \b ^ $ \A \z
  • 轉義字符: \1 \2 \3 etc. (在匹配表達式和替換表達式中均可用)
  • 元字符: . \ [ ] { } ? * + | ( ) ^ $
  • 在字符類中使用元字符: [ ] \ - ^
  • 使用反斜槓能夠忽略元字符: \

 致謝

正則表達式很是經常使用並且很是有用。每一個人在編輯文本或是編寫程序時都必須瞭解怎樣使用正則表達式。

練習

選擇正則表達式的某種實現,閱讀相關文檔。我保證,你會學到更多。

相關文章
相關標籤/搜索