主頁 > 知識庫 > 正則表達式高級學(xué)習(xí)技巧

正則表達式高級學(xué)習(xí)技巧

熱門標(biāo)簽:銀行業(yè)務(wù) 科大訊飛語音識別系統(tǒng) 服務(wù)器配置 Linux服務(wù)器 電子圍欄 團購網(wǎng)站 阿里云 Mysql連接數(shù)設(shè)置
什么是RE?
  想必各位大大在做文件查找的時侯都有使用過萬用字符”*”,比如說想查找在Windows目錄下所有的Word文件時,你可能就會用”*.doc”這樣的方式來做查找,因為”*”所代表的是任意的字符。RE所做的就是類似這樣的功能,但其功能更為強大。

  寫程序時,常需要比對字符串是否符合特定樣式,RE最主要的功能就是來描述這特定的樣式,因此可以將RE視為特定樣式的描述式,舉個例子來說,”\w+”所代表的就是任何字母與數(shù)字所組成的非空字符串(non-null string)。在.NET framework中提供了非常強大的類別庫,藉此可以很輕易的使用RE來做文字的查找與取代、對復(fù)雜標(biāo)頭的譯碼及驗證文字等工作。
接下來,就讓我們來體驗一些例子吧。

  一些簡單的例子
  假設(shè)要查找文章中Elvis后接有alive的文字符串的話,使用RE可能會經(jīng)過下列的過程,括號是所下RE的意思:

  1. elvis (查找elvis)

  上述代表所要查找的字符順序為elvis。在.NET中可以設(shè)定乎略字符的大小寫,所以”Elvis”、”ELVIS”或者是”eLvIs”都是符合1所下的RE。但因為這只管字符出現(xiàn)的順序為elvis,所以pelvis也是符合1所下的RE??梢杂?的RE來改進。

  2. \belvis\b (將elvis視為一整體的字查找,如elvis、Elvis乎略字符大小寫時)
“\b”在RE中有特別的意思,在上述的例子中所指的就是字的邊界,所以\belvis\b用\b把elvis的前后邊界界定出來,也就是要elvis這個字。

  假設(shè)要將同一行里elvis后接有alive的文字符串找出來,此時就會用到另外二個特別意義的字符”.”及”*”?!?”所代表就是除了換行字符的任意字符,而”*”所代表的是重復(fù)*之前項目直到找到符合RE的字符串。所以”.*”所指的就是除了換行字符外的任意數(shù)目的字符數(shù)。所以查找同一行里elvis后接有alive的文字符串找出來,則可下如3之RE。

  3. \belvis\b.*\balive\b (查找elvis后面接有alive的文字符串,如elvis is alive)

  用簡單之特別字符就可以組成功能強大的RE,但也發(fā)現(xiàn)當(dāng)使用越來越多的特別字符時,RE就會越來越難看得懂了。


再看看另外的例子
  組成有效的電話號碼

  假使要從網(wǎng)頁上收集顧客格式為xxx-xxxx的7位數(shù)字的電話號碼,其中x是數(shù)字,RE可能會這樣寫。

  4. \b\d\d\d-\d\d\d\d (查找七位數(shù)字之電話號碼,如123-1234)
  每一個\d代表一個數(shù)字?!?”則是一般的連字符號,為避免太多重復(fù)的\d,RE可以改寫成如5的方式。

  5. \b\d{3}-\d{4} (查找七位數(shù)字電話號碼較好的方法,如123-1234)
  在\d后的{3},代表重復(fù)前一個項目三次,也就是相等于\d\d\d。

  RE的學(xué)習(xí)及測試工具 Expresso

  因為RE不易閱讀及使用者容易會下錯RE的特性,Jim大大開發(fā)了一個工具軟件Expresso,用來幫助使用者學(xué)習(xí)及測試RE,除了上面所述的網(wǎng)址之外,也可以上Ultrapico網(wǎng)站。安裝完expresso后,在expression%20%20library中,jim大大把文章的例子都建立在其中,可以邊看文章邊測試,也可以試著修改范例所下的re,馬上可以看到結(jié)果,小弟覺得非常好用。各位大大可以試試。/"。安裝完Expresso后,在Expression Library中,Jim大大把文章的例子都建立在其中,可以邊看文章邊測試,也可以試著修改范例所下的RE,馬上可以看到結(jié)果,小弟覺得非常好用。各位大大可以試試。 

  .NET中RE的基礎(chǔ)概念
  特殊字符

  有些字符有特別的意義,比如之前所看到的”\b”、”.”、”*”、”\d”等。”\s”所代表的是任意空格符,比如說spaces、tabs、newlines等.?!盶w”代表是任意字母或數(shù)字字符。

  再看一些例子吧
  6. \ba\w*\b (查找a開頭的字,如able)
  這RE描述要查找一個字的開始邊界(\b),再來是字母”a”,再加任意數(shù)目的字母數(shù)字(\w*),再接結(jié)束這個字的結(jié)束邊界(\b)。

  7. \d+ (查找數(shù)字字符串)
  “+”和”*”非常相似,除了+至少要重復(fù)前面的項目一次。也就是說至少有一個數(shù)字。

  8. \b\w{6}\b (查找六個字母數(shù)字的字,如ab123c)

  下表為RE常用的特殊字符

  . 除了換行字符的任意字符
  \w 任意字母數(shù)字字符
  \s 任意空格符
  \d 任意數(shù)字字符
  \b 界定字的邊界
  ^ 文章的開頭,如”^The'' 用以表示出現(xiàn)于文章開頭的字符串為”The”
  $ 文章的結(jié)尾,如”End$”用以表示出現(xiàn)在文章的結(jié)尾為”End”
  特殊字符”^”及”$”是用來查找某些字必需是文章的開頭或結(jié)尾,這在驗證輸入是否符合某一樣式時特別用有,比如說要驗證七位數(shù)字的電話號碼,可能會輸入如下9的RE。

  9. ^\d{3}-\d{4}$ (驗證七位數(shù)字之電話號碼)

  這和第5個RE相同,但其前后都無其它的字符,也就是整串字符串只有這七個數(shù)字的電話號碼。在.NET中如果設(shè)定Multiline這個選項,則”^”和”$”會每行進行比較,只要某行的開頭結(jié)尾符合RE即可,而不是整個文章字符串做一次比較。

  轉(zhuǎn)意字符(Escaped characters)

  有時可能會需要”^”、”$”單純的字面意義(literal meaning)而不要將它們當(dāng)成特殊字符,此時”\”字符就是用來移除特殊字符特別意義的字符,因此”\^”、”\.”、”\\”所代表的就是”^”、”.”、”\”的字面意義。

  重復(fù)前述項目

  在前面看過”{3}”及”*”可以用來重復(fù)前述字符,之后我們會看到如何用同樣的語法重復(fù)整個次描述(subexpressions)。下表是使用重復(fù)前述項目的一些方式。

  * 重復(fù)任意次數(shù)
  + 重復(fù)至少一次
  ? 重復(fù)零次或一次
  {n} 重復(fù)n次
  {n,m} 重復(fù)至少n次,但不超過m次
  {n,} 重復(fù)至少n次

  再來試一些例子吧

  10. \b\w{5,6}\b (查找五個或六個字母數(shù)字字符的字,如as25d、d58sdf等)
  11. \b\d{3}\s\d{3}-\d{4} (查找十個數(shù)字的電話號碼,如800 123-1234)
  12. \d{3}-\d{2}-\d{4} (查找社會保險號碼,如 123-45-6789)
  13. ^\w* (每行或整篇文章的第一個字)
  在Espresso可試試有Multiline和沒Multiline的不同。

  匹配某范圍的字符

  有時需要查找某些特定的字符時怎么辨?這時中括號”[]”就派上了用場。因此[aeiou]所要查找的是”a”、”e”、”i”、”o”、”u”這些元音,[.?!]所要查找的是”.”、”?”、”!”這些符號,在中括號中的特殊字符的特別意義都會被移除,也就是解譯成單純的字面意義。也可以指定某些范圍的字符,如”[a-z0-9]”,所指的就是任意小寫字母或任意數(shù)字。

  接下來再看一個比較初復(fù)雜查找電話號碼的RE例子

  14. \(?\d{3}[( ] \s?\d{3}[- ]\d{4} (查找十位數(shù)字之電話號碼,如(080) 333-1234 )

  這樣的RE可查找出較多種格式的電話號碼,如(080) 123-4567、511 254 6654等?!盶(?”代表一個或零個左小括號”(“,而”[( ]”代表查找一個右小括號”)”或空格符,”\s?”指一個或零個空格符組。但這樣的RE會將類似”800) 45-3321”這樣的電話找出來,也就是括號沒有對稱平衡的問題,之后會學(xué)到擇一(alternatives)來決解這樣的問題。

  不包含在某特定字符組里(Negation)

  有時需要查找在包含在某特定字符組里的字符,下表說明如何做類似這樣的描述。

  \W 不是字母數(shù)字的任意字符
  \S 不是空格符的任意字符
  \D 不是數(shù)字字符的任意字符
  \B 不在字邊界的位置
  [^x] 不是x的任意字符
  [^aeiou] 不是a、e、i、o、u的任意字符

  15. \S+ (不包含空格符的字符串)

  擇一(Alternatives)

  有時會需要查找?guī)讉€特定的選擇,此時”|”這個特殊字符就派上用場了,舉例來說,要查找五個數(shù)字及九個數(shù)字(有”-”號)的郵政編碼。

  16. \b\d{5}-\d{4}\b|\b\d{5}\b (查找五個數(shù)字及九個數(shù)字(有”-”號)的郵政編碼)

  在使用Alternatives時需要注意的是前后的次序,因為RE在Alternatives中會優(yōu)先選擇符合最左邊的項目,16中,如果把查找五個數(shù)字的項目放在前面,則這RE只會找到五個數(shù)字的郵政編碼。了解了擇一,可將14做更好的修正。

  17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} (十個數(shù)字的電話號碼)

  群組(Grouping)

  括號可以用來介定一個次描述,經(jīng)由次描述的介定,可以針對次描述做重復(fù)或及他的處理。

  18. (\d{1,3}\.){3}\d{1,3} (尋找網(wǎng)絡(luò)地址的簡單RE)

  此RE的意思第一個部分(\d{1,3}\.){3},所指的是,數(shù)字最小一位最多三位,并且后面接有”.”符號,此類型的共有三個,之后再接一到三位的數(shù)字,也就是如192.72.28.1這樣的數(shù)字。

  但這樣會有個缺點,因為網(wǎng)絡(luò)地址數(shù)字最多只到255,但上述的RE只要是一到三位的數(shù)字都是符合的,所以這需要讓比較的數(shù)字小于256才行,但只單獨使用RE并無法做這樣的比較。在19中使用擇一來將地址的限制在所需要的范圍內(nèi),也就是0到255。

  19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) (尋找網(wǎng)絡(luò)地址)

  有沒有發(fā)覺RE越來越像外星人說的話了?就以簡單的尋找網(wǎng)絡(luò)地址,直接看RE都滿難理解的哩。

  Expresso Analyzer View

  Expresso提供了一個功能,它可以將所下的RE變成樹狀的說明,一組組的分開說明,提供了一個好的除錯環(huán)境。其它的功能,如部分符合(Partial Match只查找反白RE的部分)及除外符合(Exclude Match只不查找反白RE的部分)就留給各位大大試試啰。

  當(dāng)次描述用括號群組起來時,符合次描述的文字可用在之后的程序處理或RE本身。在預(yù)設(shè)的情型下,所符合的群組是由數(shù)字命名,由1開始,由順序是由左至右,這自動群組命名,可在Expresso中的skeleton view或result view中看到。

  Backreference是用來查找群組中抓取的符合文字所相同的文字。舉例來說”\1”所指符合群組1所抓取的文字。

  20. \b(\w+)\b\s*\1\b (尋找重復(fù)字,此處說的重復(fù)是指同樣的字,中間有空白隔開如dog dog這樣的字)
(\w+)會抓取至少一個字符的字母或數(shù)字的字,并將它命名為群組1,之后是查找任意空格符,再接和群組1相同的文字。

  如果不喜歡群組自動命名的1,也可以自行命名,以上述例子為例,(\w+)改寫為(?Word>\w+),這就是將所抓取的群組命名為Word,Backreference就要改寫成為\kWord>
21. \b(?Word>\w+)\b\s*\kWord>\b (使用自行命名群組抓取重復(fù)字)

  使用括號還有許多特別的語法元素,比較通用的列表如下:

  抓取(Captures) 
  (exp) 符合exp并抓取它進自動命名的群組
  (?name>exp) 符合exp并抓取它進命名的群組name
  (?:exp) 符合exp,不抓取它
  Lookarounds 
  (?=exp) 符合字尾為exp的文字
  (?=exp) 符合前綴為exp的文字
  (?!exp) 符合后面沒接exp字尾的文字
  (?!exp) 符合前面沒接exp前綴的文字
  批注Comment 
  (?#comment) 批注

  Positive Lookaround

  接下來要談的是lookahead及l(fā)ookbehind assertions。它們所查找的是目前符合之前或之后的文字,并不包含目前符合本身。這些就如同”^”及”\b”特殊字符,本身并不會對應(yīng)任何文字(用來界定位置),也因此稱做是zero-width assertions,看些例子也許會清楚些。

  (?=exp)是一個”zero-width positive lookahead assertion”。它指的就是符合字尾為exp的文字,但不包含exp本身。

  22. \b\w+(?=ing\b) (字尾為ing的字,比如說filling所符合的就是fill)
(?=exp)是一個”zero-width positive lookbehind assertion”。它指的就是符合前綴為exp的文字,但不包含exp本身。

  23. (?=\bre)\w+\b (前綴為re的字,比如說repeated所符合的就是peated)
  24. (?=\d)\d{3}\b (在字尾的三位數(shù)字,且之前接一位數(shù)字)
  25. (?=\s)\w+(?=\s) (由空格符分隔開的字母數(shù)字字符串)

  Negative Lookaround

  之前有提到,如何查找一個非特定或非在特定群組的字符。但如果只是要驗證某字符不存在而不要對應(yīng)這些字符進來呢?舉個例子來說,假設(shè)要查找一個字,它的字母里有q但接下來的字母不是u,可以用下列的RE來做。

  26. \b\w*q[^u]\w*\b (一個字,其字母里有q但接下來的字母不是u)

  這樣的RE會有一個問題,因為[^u]要對應(yīng)一個字符,所以若q是字的最后一個字母,[^u]這樣的下法就會將空格符對應(yīng)下去,結(jié)果就有可能會符合二個字,比如說”Iraq haha”這樣的文字。使用Negative Lookaround就能解決這樣的問題。

  27. \b\w*q(?!u)\w*\b (一個字,其字母里有q但接下來的字母不是u)
  這是”zero-width negative lookahead assertion”。

  28. \d{3}(?!\d) (三個位的數(shù)字,其后不接一個位數(shù)字)

  同樣的,可以使用(?!exp),”zero-width negative lookbehind assertion”,來符合前面沒接exp前綴的文字符串。

  29. (?![a-z ])\w{7} (七個字母數(shù)字的字符串,其前面沒接字母或空格)

30. (?=(\w+)>.*(?=\/\1> (HTML卷標(biāo)間的文字)
  這使用lookahead及l(fā)ookbehind assertion來取出HTML間的文字,不包括HTML卷標(biāo)。

  請批注(Comments Please)
  括號還有個特殊的用途就是用來包住批注,語法為”(?#comment)”,若設(shè)定”Ignore Pattern Whitespace”選項,則RE中的空格符當(dāng)RE使用時會乎略。此選項設(shè)定時,”#”之后的文字會乎略。

  31. HTML卷標(biāo)間的文字,加上批注

  (?=  #查找前綴,但不包含它
  (\w+)> #HTML標(biāo)簽
  ) #結(jié)束查找前綴
  .* #符合任何文字
  (?= #查找字尾,但不包含它
  \/\1> #符合所抓取群組1之字符串,也就是前面小括號的HTML標(biāo)簽
  ) #結(jié)束查找字尾

  尋找最多字符的字及最少字符的字(Greedy and Lazy)
  當(dāng)RE下要查找一個范圍的重復(fù)時(如”.*”),它通常會尋找最多字符的符合字,也就是Greedy matching。舉例來說。

  32. a.*b (開始為a結(jié)束為b的最多字符的符合字)

  若有一字符串是”aabab”,使用上述RE所得到的符合字符串就是”aabab”,因為這是尋找最多字符的字。有時希望是符合最少字符的字也就是lazy matching。只要將重復(fù)前述項目的表加上問號(?)就可以把它們?nèi)孔兂蒷azy matching。因此”*?”代表的就是重復(fù)任意次數(shù),但是使用最少重復(fù)的次數(shù)來符合。舉個例子來說:

  33. a.*?b (開始為a結(jié)束為b的最少字符的符合字)

  若有一字符串是”aabab”,使用上述RE第一個所得到的符合字符串就是”aab”再來是”ab”,因為這是尋找最少字符的字。

  *? 重復(fù)任意次數(shù),最少重復(fù)次數(shù)為原則
  +? 重復(fù)至少一次,最少重復(fù)次數(shù)為原則
  ?? 重復(fù)零次或一次,最少重復(fù)次數(shù)為原則
  {n,m}? 重復(fù)至少n次,但不超過m次,最少重復(fù)次數(shù)為原則
  {n,}? 重復(fù)至少n次,最少重復(fù)次數(shù)為原則

還有什么沒提到呢?

  到目前為止,已經(jīng)提到了許多建立RE的元素,當(dāng)然還有許多元素沒有提到,下表整理了一些沒提到的元素,在最左邊的字段的數(shù)字是說明在Expresso中的例子。

  # 語法 說明

  \a Bell 字符
  \b 通常是指字的邊界,在字符組里所代表的就是backspace
  \t Tab

  34 \r Carriage return

  \v Vertical Tab
  \f From feed

  35 \n New line
  \e Escape

  36 \nnn ASCII八位碼為nnn的字符

  37 \xnn 十六位碼為nn的字符

  38 \unnnn Unicode為nnnn的字符

  39 \cN Control N字符,舉例來說Ctrl-M是\cM

  40 \A 字符串的開始(和^相似,但不需籍由multiline選項)

  41 \Z 字符串的結(jié)尾
  \z 字符串的結(jié)尾

  42 \G 目前查找的開始

  43 \p{name} Unicode 字符組名稱為name的字符,比如說\p{Lowercase_Letter} 所指的就是小寫字
  (?>exp) Greedy次描述,又稱之為non-backtracking次描述。這只符合一次且不采backtracking。

  44 (?x>-y>exp)

  or (?-y>exp) 平衡群組。雖復(fù)雜但好用。它讓已命名的抓取群組可以在堆棧中操作使用。(小弟對這個也是不太懂哩)

  45 (?im-nsx:exp) 為次描述exp更改RE選項,比如(?-i:Elvis)就是把Elvis大乎略大小寫的選項關(guān)掉

  46 (?im-nsx) 為之后的群組更改RE選項。
  (?(exp)yes|no) 次描述exp視為zero-width positive lookahead。若此時有符合,則yes次描述為下一個符合標(biāo)的,若否,則no 次描述為下一個符合標(biāo)的。
  (?(exp)yes) 和上述相同但無no次描述
  (?(name)yes|no) 若name群組為有效群組名稱,則yes次描述為下一個符合標(biāo)的,若否,則no 次描述為下一個符合標(biāo)的。

  47 (?(name)yes) 和上述相同但無no次描述
您可能感興趣的文章:
  • ASP正則表達式技巧
  • PHP 正則表達式的幾則使用技巧
  • 正則表達式高級技巧及實例詳解 笨活兒
  • javascript 正則表達式(二) 使用技巧說明
  • 模板引擎正則表達式調(diào)試小技巧
  • 正則表達式的高級技巧分享
  • .NET 正則表達式使用高級技巧之替換類介紹
  • 正則表達式匹配不包含某些字符串的技巧
  • 寫出高效率的正則表達式技巧總結(jié)

標(biāo)簽:萍鄉(xiāng) 大理 江蘇 衢州 棗莊 蚌埠 衡水 廣元

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《正則表達式高級學(xué)習(xí)技巧》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266