正則表達式簡明教程(持續更新中)

前言

這是一份比較簡單的正則表達式指南,是我按照本身學習正則時作的筆記整理出來的,並不能保證沒有瑕疵,但我會盡最大可能來完善它,特此我在標題上加上了 持續更新

格式

爲了使你們更加容易閱讀,我在使用了幾處高亮, 例子統一用黃色標註, 注意事項使用紅色警示, 專業術語加粗。

目錄

  1. 引言
  2. 什麼事正則表達式
  3. 元字符
  4. 重複
  5. 轉義字符
  6. 反義
  7. 字符類
  8. 分支條件
  9. 分組
  10. 向後引用
  11. 零寬斷言
  12. 負向零寬斷言
  13. 註釋
  14. 貪婪與懶惰
  15. 附錄

引言

最近給大一講解了下正則表達式,順便整理了份資料,共享出來。可能有點小誤差,可是正如題目中所說的,這是一篇不斷完善,不斷擴充的博文。 好了,言歸正傳,咱們平時會遇到比較多的字符串,尤爲是在處理文本的時候,我想這方面作Linux運維的應該深有體會。若是咱們須要搜索某個文本中 具備某種規律的字符串時應該怎麼辦呢?很明顯grep+正則。下面我就來簡單介紹下什麼是正則表達式,以及它的用法。

什麼是正則表達式?

在計算機科學中,是指一個用來描述或者匹配一系列符合某個句法規則的字符串的單個字符串。如,咱們可使用 25[0-5]|2[0-4]\d|^1?[1-9]?\d$來匹配0-255。

元字符

\b 匹配字符串的開始或結束(隔離空格)
\w 匹配字母、數字、下劃線或漢字
\s 匹配任意的空白符
^ 匹配字符串的開始
$ 匹配字符串的結束
. 匹配除換行符之外的任意字符
\0nn 匹配ASCII中八進制代碼爲nn的字符
\xnn 匹配ASCII中十六進制代碼爲nn的字符
\unnnn 匹配Unicode中十六進制代碼爲nn的字符
\cN 匹配ASCII控制符
這些都是十分基礎的元字符,下面咱們給出2個例子:
  1. ^\d\s\d$ 這條正則表達式表示一個字符串,它的特徵是以數字開始和結束,而且兩個數字之間有個空格
  2. \btt\b 這條正則表達式可以識別「cattac tt」中的後一個「tt

重複

* 重複零次或更屢次
+ 重複一次或屢次
? 重複零次或一次
{n} 重複n次
{n,} 重複n次或更多
{n,m} 重複n到m次
重複若是使用得當,可以極大地縮短正則表達式地長度,如下是2個簡單的例子:
  1. Linux\d+ 這條表達式可以匹配Linux以及其後更隨的至少一個數字,有點拗口,打個比方,Linux3
  2. \b\d{7}\b 這條表達式將可以匹配獨立的7個數字組成的字符串

轉義字符

從上面的元字符中咱們能夠看到有些字符被正則表達式給佔用了,此時咱們就須要將他們轉義,十分簡單,咱們只須要在被佔用的字符前面加上\,對就像大多數程序語言同樣處理就好了,如\.,\^,\$,\\,\(,\)等等。
\a 報警
\t 製表符
\v 豎向製表符
\f 換頁符
\n 換行符
\e Esc

反義

\W 匹配任意不是\w的字符
\S 匹配任意不是\s的字符
\D 匹配任意不是\d的字符
\B 匹配任意不是\b的位置
[^x] 匹配除了x之外的任意字符
[^as] 匹配除了as之外的任意字符
反義就至關於元字符的補集,其中的\B比較難以理解。 那麼,咱們來深究下\b到底表示的是什麼東西?它表示一個特殊位置,即字符與空格之間的位置。 由此類比,\B表示的是字符與字符之間的位置,不過這裏的字符並不包括空白字符。 \B並不經常使用,它包含的位置實在是太具廣泛性了。。。 一樣,咱們給出2個例子:
  1. \b[^z]+\b 匹配不含z的字符串
  2. <s[^>\s]+> 匹配用<>括起來的以s開頭的不包含空格的字符串

字符類

上述的\d表示數字0-9,那麼假設咱們只須要匹配2-5,那麼該怎麼辦?顯然,到目前爲止,咱們並無提到相關技術。 此時咱們須要的是本身定義字符類了,方法很簡單,使用[]將你須要定義的字符類括起來就好了,如下是幾個例子:
  1. [2-5] 表示匹配2-5,固然你徹底可使用[2345],若是你不嫌累的話
  2. [a-z] 匹配全部小寫字母
  3. [a-zA-Z] 匹配全部大小寫字母

分支條件

什麼是分支條件呢?請不要着急,咱們先來說述一個案例。 假設如今咱們有2串電話號碼,分別是(010)12345678和010-12345678,它們均是某電話號碼的合法表示,那麼咱們應該如何來經過正則表達式來匹配呢? 很簡單,使用分支——「|」,也能夠理解爲「或」。接下來咱們就試着用分支來解決上述問題。
  1. \(010\)\d{8}匹配(010)那種表示方式
  2. 010-\d{8}匹配另一種
  3. 咱們將上述兩個式子經過|鏈接,即(\(010\)|010-)\d{8}

分組

細心的讀者應該會發現,到目前爲止咱們所針對都是單個字符的匹配,那麼一段字符串如何精確匹配? 這個時候咱們就要引入「分組」的概念了。所謂分組,其實就是使用()將須要匹配的字符串括起來,這個時候的重複就是針對整個括號內的內容了。同時,分組也爲咱們引入新的概念奠基了基礎,這個後面會提到。 用例子來講話:
  1. ([a-z]\d)+ 匹配一個或者多個以小寫字母和數字的組合
  2. (\d{3}.){3}\d{3} 實現一字符串,其具體形式相似於ip,只是其有效值爲000-999,咱們暫時不考慮複雜的例子

向後引用

其實分組還有個特性,那就是它的識別字符會被引擎直接標號,供咱們接下來直接引用,下面咱們就來介紹這方面的特性。 首先是格式,這裏的具體格式有兩種,其一是使用默認組號;其二是自定義標記。下面咱們分開來介紹。 默認形式\b(\w+)\b\s+\b\1\b 我將相關部分使用紅色標識了,這裏的第一個分組內容被引擎匹配後,會被編上號碼(注意,是從1開始的),接下來咱們就能夠經過\1來引用了 用戶定義 \b(?<Word>\w+)\b\s+\b\k<Word>\b 這個表達式的功能和上面是同樣的只是咱們此時將默認標識換成了本身定義的標誌,不過這裏其實還有另外一種形式 \b(?'Word'\w+)\b\s+\b\k'Word'\b 

零寬斷言

零寬斷言,聽起來很玄乎,其實它和以前介紹的^,$,\b同樣,都是用來標識一個位置,只不過咱們能夠自由定義這個位置罷了。 (?=exp)也叫 零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表達式 exp。好比 \b\w+(?=ing\b),匹配以ing結尾的單詞的前面部分(除了ing之外的部分),如查找I'm singing while you're dancing.時,它會匹配sing和danc。 (?<=exp)也叫 零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表達式 exp。好比 (?<=\bre)\w+\b會匹配以re開頭的單詞的後半部分(除了re之外的部分),例如在查找reading a book時,它匹配ading。 下面這個例子同時使用了這兩種斷言:
  • (?<=\s)\d+(?=\s)匹配以空白符間隔的數字(不包括這些空白符)。

負向零寬斷言

零寬斷言是定義符合條件的位置,那麼必然,它是有補集的,那就是負向零寬斷言。多位負向零寬斷言,就是指不符合定義的位置。 (?!exp)也叫 零寬度負預測先行斷言,斷言此位置的後面不能匹配表達式 exp。例如: \d{3}(?!\d)匹配三位數字,並且這三位數字的後面不能是數字; \b((?!abc)\w)+\b匹配不包含連續字符串abc的單詞。 (?<!exp)也叫 零寬度負回顧後發斷言,斷言此位置的前面不能匹配表達式 exp。例如: (?<![a-z])\d{7}匹配前面不是小寫字母的七位數字。

註釋

就像程序語言可以添加註釋同樣,正則表達式也是能夠的,尤爲是在式子比較長的時候,註釋顯得尤其重要。使用註釋的方式就是(?#comment),例如 2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)

貪婪與懶惰

正則表達式是具備雙重人格的,爲何這麼說呢?且看本段。 當正則表達式中包含能接受重複的限定符時,一般的行爲是匹配儘量多的字符。例如: a.*b,它將會匹配最長的以a開始,以b結束的字符串。若是用它來搜索aabab的話,它會匹配整個字符串aabab。這就是 貪婪匹配。 有時,咱們更須要 懶惰匹配——匹配儘量少的字符。前面給出的限定符均可以被轉化爲懶惰匹配模式,只要在它後面加上一個問號?。這樣.*?就意味着匹配任意數量的重複,可是在能使整個匹配成功的前提下使用最少的重複。例如: a.*?b匹配最短的,以a開始,以b結束的字符串。若是把它應用於aabab的話,它會匹配aabab
*? 重複任意次,但儘量少重複
+? 重複1次或更多,但儘量少重複
?? 重複0次或1次,但儘量少重複
{n,m}? 重複n到m次,但儘量少重複
{n,}? 重複n次以上,但儘量少重複

附錄

修改記錄:

2013-3-8 --> 編寫正則表達式最基礎的知識點


如要轉載本人的文章,請註明出處。

相關文章
相關標籤/搜索