今天下午“光榮”的分到了59個bug,磨刀不誤砍柴工,先學一下正則表達式……入門\b是正則表達式規定的一個特殊代碼(好吧,某些人叫它元字符,metacharacter),代表著單詞的開頭或結尾,也就是單詞的分界處。雖然通常英文的單詞是由空格,標點符號或者換行來分隔的,但是\b并不匹配這些單詞分隔字符中的任何一個,它只匹配一個位置。如果需要更精確的說法,\b匹配這樣的位置:它的" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

正則表達式--筆記與實戰(Eclipse文本替換)

系統 1953 0
<style> <!-- .p {text-indent:2em} --> </style>

今天下午“光榮”的分到了59個bug,磨刀不誤砍柴工,先學一下正則表達式……

入門

\b 是正則表達式規定的一個特殊代碼(好吧,某些人叫它 元字符,metacharacter ),代表著 單詞的開頭或結尾,也就是單詞的分界處 。雖然通常英文的單詞是由空格,標點符號或者換行來分隔的,但是 \b 并不匹配這些單詞分隔字符中的任何一個,它 只匹配一個位置

如果需要更精確的說法, \b 匹配這樣的位置:它的前一個字符和后一個字符不全是(一個是,一個不是或不存在) \w

假如你要找的是 hi后面不遠處跟著一個Lucy ,你應該用 \bhi\b.*\bLucy\b 。若要匹配"A B",則使用 A\sB 或者 A\b\s\bB 等。 表達式 " . \b . " 在匹配 "@@@abc" 時 ,匹配結果是:成功;匹配到的內容是:"@a";匹配到的位置是:開始于2,結束于4。 表達式 " \b end \b " 在匹配 "weekend,endfor,end" 時 ,匹配結果是:成功;匹配到的內容是:"end";匹配到的位置是:開始于15,結束于18。

這里, . 是另一個元字符,匹配 除了換行符以外的任意字符 * 同樣是元字符,不過它代表的不是字符,也不是位置,而是數量——它指定* 前邊的內容可以連續重復使用任意次以使整個表達式得到匹配 。因此, .* 連在一起就意味著 任意數量的不包含換行的字符 。?匹配 重復零次或一次

元字符

\s 匹配 任意的空白符,包括空格,制表符(Tab),換行符,中文全角空格等 \w 匹配 字母或數字或下劃線或漢字等

對中文/漢字的特殊處理是由.Net提供的正則表達式引擎支持的,其它環境下的具體情況請查看相關文檔。

和忽略大小寫的選項類似,有些正則表達式處理工具還有一個處理多行的選項。如果選中了這個選項, ^ $ 的意義就變成了 匹配行的開始處和結束處

分枝條件

\(?0\d{2}[) -]?\d{8}

“(”和“)”也是元字符,后面的分組節里會提到,所以在這里需要使用轉義。

這個表達式可以匹配 幾種格式的電話號碼 ,像 (010)88886666 ,或 022-22334455 ,或 02912345678 等。


不幸的是,剛才那個表達式也能匹配 010)12345678 (022-87654321 這樣的“不正確”的格式。要解決這個問題,我們需要用到 分枝條件 。正則表達式里的 分枝條件 指的是有幾種規則,如果滿足其中任意一種規則都應該當成匹配,具體方法是用 | 把不同的規則分隔開。聽不明白?沒關系,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7} 這個表達式能 匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)

\(?0\d{2}\)?[- ]?\d{8}|0\d{2}[- ]?\d{8} 這個表達式 匹配3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔 。你可以試試用分枝條件把這個表達式擴展成也支持4位區號的。

\d{5}-\d{4}|\d{5} 這個表達式用于匹配美國的郵政編碼。美國郵編的規則是5位數字,或者用連字號間隔的9位數字。之所以要給出這個例子是因為它能說明一個問題: 使用分枝條件時,要注意各個條件的順序 。如果你把它改成 \d{5}|\d{5}-\d{4} 的話,那么就只會匹配5位的郵編(以及9位郵編的前5位)。原因是匹配分枝條件時,將會從左到右地測試每個條件,如果滿足了某個分枝的話,就不會去再管其它的條件了。

反義

代碼/語法 說明 常用的反義代碼
\W 匹配任意不是字母,數字,下劃線,漢字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非數字的字符
\B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou這幾個字母以外的任意字符

例:<a[^>]+> 匹配 用尖括號括起來的以a開頭的字符串

分組與后向引用

可以用小括號來指定 子表達式 (也叫做 分組 ),然后你就可以指定這個子表達式的重復次數了。例如: 描述一個正確的IP地址: ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

使用小括號指定一個子表達式后,匹配這個子表達式的文本(也就是此分組捕獲的內容)可以在表達式或其它程序中作進一步的處理。默認情況下,每個分組會自動擁有一個 組號 分組0對應整個正則表達式。 后向引用 用于重復搜索前面某個分組匹配的文本。例如, \1 代表 分組1匹配的文本 \b(\w+)\b\s+\1\b 可以用來匹配 重復的單詞 ,像 go go , 或者 kitty kitty

實際上組號分配過程是要從左向右掃描兩遍的:第一遍只給未命名組分配,第二遍只給命名組分配--因此所有命名組的組號都大于未命名的組號, 你可以使用 (?:exp) 這樣的語法來剝奪一個分組對組號分配的參與權。

你也可以自己指定子表達式的 組名 (?<Word>\w+) (或者把尖括號換成 ' 也行: (?'Word'\w+) ),這樣就把 \w+ 的組名指定為 Word 了。要反向引用這個分組 捕獲 的內容,你可以使用 \k<Word> ,所以上一個例子也可以寫成這樣: \b(?<Word>\w+)\b\s+\k<Word>\b

使用小括號的時候,還有很多特定用途的語法。下面列出了最常用的一些:

分類 代碼/語法 說明 捕獲 零寬斷言 注釋 常用分組語法
(exp) 匹配exp,并捕獲文本到自動命名的組里
(?<name>exp) 匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?'name'exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
(?#comment) 這種類型的分組不對正則表達式的處理產生任何影響,用于提供注釋讓人閱讀

零寬斷言

斷言用來聲明一個應該為真的事實。正則表達式中只有當斷言為真時才會繼續進行匹配。 接下來的四個用于查找在某些內容(但并不包括這些內容)之前或之后的東西,也就是說它們像 \b , ^ , $ 那樣用于指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱為 零寬斷言

(?=exp) 也叫 零寬度正預測先行斷言 ,它 斷言自身出現的位置的后面能匹配表達式exp 。比如 \b\w+(?=ing\b) ,匹配 以ing結尾的單詞的前面部分(除了ing以外的部分) ,如查找 I'm singing while you're dancing. 時,它會匹配 sing danc \b(?=\w{7}\b)\w*clip\w*\b ,匹配包含clip的七個字符的單詞。

(?<=exp) 也叫 零寬度正回顧后發斷言 ,它 斷言自身出現的位置的前面能匹配表達式exp 。比如 (?<=\bre)\w+\b 會匹配 以re開頭的單詞的后半部分(除了re以外的部分) ,例如在查找 reading a book 時,它匹配 ading

假如你想要給一個很長的數字中每三位間加一個逗號(當然是從右邊加起了),你可以這樣查找需要在前面和里面添加逗號的部分: ((?<=\d)\d{3})+\b ,用它對 1234567890 進行查找時結果是 234567890

下面這個例子同時使用了這兩種斷言: (?<=\s)\d+(?=\s) 匹配 以空白符間隔的數字(再次強調,不包括這些空白符)

負向零寬斷言

前面我們提到過怎么查找 不是某個字符或不在某個字符類里 的字符的方法(反義)。但是如果我們只是想要 確保某個字符沒有出現,但并不想去匹配它 時怎么辦?例如,如果我們想查找這樣的單詞--它里面出現了字母q,但是q后面跟的不是字母u,我們可以嘗試這樣:

\b\w*q[^u]\w*\b 匹配 包含 后面不是字母u的字母q 的單詞 。但是如果多做測試(或者你思維足夠敏銳,直接就觀察出來了),你會發現,如果q出現在單詞的結尾的話,像 Iraq , Benq ,這個表達式就會出錯。這是因為 [^u] 總要匹配一個字符,所以如果q是單詞的最后一個字符的話,后面的 [^u] 將會匹配q后面的單詞分隔符(可能是空格,或者是句號或其它的什么),后面的 \w*\b 將會匹配下一個單詞,于是 \b\w*q[^u]\w*\b 就能匹配整個 Iraq fighting 負向零寬斷言 能解決這樣的問題,因為它只匹配一個位置,并不 消費 任何字符。現在,我們可以這樣來解決這個問題: \b\w*q(?!u)\w*\b

零寬度負預測先行斷言 (?!exp) 斷言此位置的后面不能匹配表達式exp 。例如: \d{3}(?!\d) 匹配 三位數字,而且這三位數字的后面不能是數字 \b((?!abc)\w)+\b 匹配 不包含連續字符串abc的單詞

同理,我們可以用 (?<!exp) , 零寬度負回顧后發斷言 斷言此位置的前面不能匹配表達式exp (?<![a-z])\d{7} 匹配 前面不是小寫字母的七位數字

請詳細分析表達式 (?<=<(\w+)>).*(?=<\/\1>) ,這個表達式最能表現零寬斷言的真正用途。

一個更復雜的例子: (?<=<(\w+)>).*(?=<\/\1>) 匹配 不包含屬性的簡單HTML標簽內里的內容 (?<=<(\w+)>) 指定了這樣的 前綴 被尖括號括起來的單詞 (比如可能是<b>),然后是 .* (任意的字符串),最后是一個 后綴 (?=<\/\1>) 。注意后綴里的 \/ ,它用到了前面提過的字符轉義; \1 則是一個反向引用,引用的正是 捕獲的第一組 ,前面的 (\w+) 匹配的內容,這樣如果前綴實際上是<b>的話,后綴就是</b>了。整個表達式匹配的是<b>和</b>之間的內容(再次提醒,不包括前綴和后綴本身)。

貪婪與懶惰

當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配 盡可能多 的字符。以這個表達式為例: a.*b ,它將會匹配 最長的以a開始,以b結束的字符串 。如果用它來搜索 aabab 的話,它會匹配整個字符串 aabab 。這被稱為 貪婪 匹配。

有時,我們更需要 懶惰 匹配,也就是匹配 盡可能少 的字符。前面給出的限定符都可以被轉化為懶惰匹配模式,只要在它后面加上一個問號 ? 。這樣 .*? 就意味著 匹配任意數量的重復,但是在能使整個匹配成功的前提下使用最少的重復 。現在看看懶惰版的例子吧:

a.*?b 匹配 最短的,以a開始,以b結束的字符串 。如果把它應用于 aabab 的話,它會匹配 aab(第一到第三個字符) ab(第四到第五個字符)

為什么第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)?簡單地說,因為正則表達式有另一條規則,比懶惰/貪婪規則的優先級更高:最先開始的匹配擁有最高的優先權——The match that begins earliest wins。

代碼/語法 說明 懶惰限定符
*? 重復任意次,但盡可能少重復
+? 重復1次或更多次,但盡可能少重復
?? 重復0次或1次,但盡可能少重復
{n,m}? 重復n到m次,但盡可能少重復
{n,}? 重復n次以上,但盡可能少重復


處理選項

在C#中,你可以使用Regex(String, RegexOptions)構造函數來設置正則表達式的處理選項。如:Regex regex = new Regex(@"\ba\w{6}\b", RegexOptions.IgnoreCase);

上面介紹了幾個選項如忽略大小寫,處理多行等,這些選項能用來改變處理正則表達式的方式。下面是.Net中常用的正則表達式選項:

名稱 說明 表6.常用的處理選項
IgnoreCase(忽略大小寫) 匹配時不區分大小寫。
Multiline(多行模式)

更改 ^ $ 的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結尾匹配。(在此模式下, $ 的精確含意是:匹配\n之前的位置以及字符串結束前的位置.)

例如:默認情況下,表達式 "^" 和 "$" 只匹配字符串的開始 ① 和結尾 ④ 位置。如:
①xxxxxxxxx②\n
③xxxxxxxxx④
配置為 Multiline 可以使 "^" 匹配 ① 外,還可以匹配換行符之后,下一行開始前 ③ 的位置,使 "$" 匹配 ④ 外,還可以匹配換行符之前,一行結束 ② 的位置。

Singleline(單行模式) 默認情況下,小數點 "." 匹配除了換行符(\n)以外的字符。配置為 Singleline 可使小數點可匹配包括換行符在內的所有字符。
IgnorePatternWhitespace(忽略空白) 忽略表達式中的非轉義空白并啟用由 # 標記的注釋。
ExplicitCapture(顯式捕獲) 僅捕獲已被顯式命名的組。

一個經常被問到的問題是:是不是只能同時使用多行模式和單行模式中的一種?答案是:不是。 這兩個選項之間沒有任何關系 ,除了它們的名字比較相似(以至于讓人感到疑惑)以外。

其它語法

代碼/語法 說明 其它一些語法
\a 報警字符(打印它的效果是電腦嘀一聲)
\b 通常是單詞分界位置,但如果在字符類里使用代表退格
\t 制表符,Tab
\r 回車
\v 豎向制表符
\f 換頁符
\n 換行符
\e Escape
\0nn ASCII代碼中八進制代碼為nn的字符
\xnn ASCII代碼中十六進制代碼為nn的字符
\unnnn Unicode代碼中十六進制代碼為nnnn的字符
\cN ASCII控制字符。比如\cC代表Ctrl+C
\A 字符串開頭(類似^,但不受處理多行選項的影響)
\Z 字符串結尾或行尾(不受處理多行選項的影響)
\z 字符串結尾(類似$,但不受處理多行選項的影響)
\G 當前搜索的開頭
\p{name} Unicode中命名為name的字符類,例如\p{IsGreek}
(?>exp) 貪婪子表達式
(?<x>-<y>exp) 平衡組
(?im-nsx:exp) 在子表達式exp中改變處理選項
(?im-nsx) 為表達式后面的部分改變處理選項
(?(exp)yes|no) 把exp當作零寬正向先行斷言,如果在這個位置能匹配,使用yes作為此組的表達式;否則使用no
(?(exp)yes) 同上,只是使用空表達式作為no
(?(name)yes|no) 如果命名為name的組捕獲到了內容,使用yes作為表達式;否則使用no
(?(name)yes) 同上,只是使用空表達式作為no

實戰--牛刀小試

早就傳說項目會在本月17號驗收,結果客戶突然拋出了132個bug,今天下午“光榮”的分到了59個,悲催啊 大哭 。其中一個是關于統一系統中的提示框(alert)的風格的。ctrl+H,用正則表達式 \balert\b 小搜了一下,項目里面有494處alert,其中近半數使用的是javascript標準的alert()函數,其他的是Ext提供的Ext.MessageBox.alert()或者Ext.Msg.alert()函數。我打算全部統一成Ext.Msg.alert()函數。
看著前人留下來的千奇百怪的代碼,我的蛋都碎了 驚訝 。比如大部分alert語句的形式是這樣的:
Ext.Msg
.alert(
'提示',
'請在下拉列表中選擇一條消息!');
抓狂 好吧,我就當這只是Eclipse失敗的代碼格式化功能造成的吧!
廢話不多說了,為了應對各種各樣令人蛋碎的情況,鼓搗了很久,才寫出了相應的一些正則表達式,并使用Eclipse自帶的全局Search功能,進行了相應的替換(為保險起見,先進行preview確認一下)。表達式如下:
1、 (?<!\.|//\s{0,20})\balert\b\( 替換成 Ext.Msg.alert("提示",
這樣就把所有javascript自帶的,并且沒有用“//”注釋掉的alert都替換成了Ext.Msg.alert()形式。這里的關鍵是, alert前面可以有任意空白或分隔符,也可以是一般的字符,但就是不能是點號".",匹配的時候,只匹配"alert本身",前面空格神馬的都不要。 我這里用到了所謂的 零寬度正回顧后發斷言
2、 Ext\.M(s|g|e|a|\R|\s)*\.alert\((\R|\W)*('|").*\3, 替換成 Ext.Msg.alert("提示",
這樣就把包括上面那種變態格式的代碼在內的Ext.Msg.alert和Ext.MessageBox.alert全部替換成前者,并且第一個參數統一為雙引號的"提示”。
OK,搞定!這是我第一次寫正則表達式,肯定還是可以再優化的;暫時先這樣了~
注意 上面的正則表達中,有些特性是依賴于Eclipse的,比如不依賴環境的元字符\R,表示一個換行符。另外 不要誤把Ext本身的代碼,以及系統中用到的別的第三方庫的代碼改錯咯~

New:
字符串替換實例(Java)
給定一個逗號分割的數字組成的字符串,(形如"11,1,22"),現需要刪除其中的一個數字(match),并保持原字符串的格式
下面代碼使用正則表達式,進行了兩次替換;第一次是刪除匹配到的數字,第二次是刪除掉多余的逗號

正則表達式--筆記與實戰(Eclipse文本替換)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美一区欧美二区 | 色综合色综合色综合色综合 | 婷婷综合五月中文字幕欧美 | 国产99精品视频 | 国产亚洲精品自在久久不卡 | 破外女出血一级毛片 | 亚洲欧洲国产成人精品 | 久久免费视频在线观看 | 看免费一级片 | 久久久视| 天天做人人爱夜夜爽2020毛片 | 国产精品深爱在线 | 久久精热 | 成人深夜影院 | 五月婷婷社区 | 爱操在线视频 | 黄黄网| 天天想天天干 | 欧美网站黄 | 色八戒国产一区二区三区四区 | 97香蕉久久夜色精品国产 | 久久99精品久久久久久首页 | 最近在线更新中文字幕1 | 色资源在线观看 | 亚洲国产视频在线观看 | 亚洲国产一区二区三区在线观看 | 久久99精品久久久久久综合 | 99热久久国产精品这里有99 | 看片亚洲 | 四虎影视4hutv最新地址在线 | 国产一区在线视频观看 | 国产精品久久免费 | 全免费一级午夜毛片 | 亚洲狠狠婷婷综合久久久久图片 | 久久亚洲精品成人 | 一本到在线观看视频不卡 | 成人乱色短篇合集 | 亚洲日本视频在线观看 | 免费精品久久久久久中文字幕 | 拍拍拍无挡视频免费观看1000 | 4虎 影视 免费 |