vb.net正則表示式快速入門(2)
6.使用?*或 進行重複
?:告訴引擎匹配前導字元0次或一次。事實上是表示前導字元是可選的。(問號)
:告訴引擎匹配前導字元1次或多次(空格)
*:告訴引擎匹配前導字元0次或多次(星號)
<[A-Za-z][A-Za-z0-9]*> 匹配沒有屬性的HTML標籤,“ <”以及“> ”是文字元號。
第一個字符集匹配一個字母,第二個字符集匹配一個字母或數字。
我們似乎也可以用 <[A-Za-z0-9] > 。但是它會匹配 <1> 。
但是這個正則表示式在你知道你要搜尋的字串不包含類似的無效標籤時還是足夠有效的。
限制性重複
許多現代的正則表示式實現,都允許你定義對一個字元重複多少次。
詞法是:{min,max}。min和max都是非負整數。
如果逗號有而max被忽略了,則max沒有限制。
如果逗號和max都被忽略了,則重複min次。
因此{0,}和*一樣,{1,}和的作用一樣。
你可以用 < <\b[1-9][0-9]{3}\b> > 匹配1000~9999之間的數字(“\b”表示單詞邊界)。
< <\b[1-9][0-9]{2,4}\b> > 匹配一個在100~99999之間的數字。
注意貪婪性
假設你想用一個正則表示式匹配一個HTML標籤。你知道輸入將會是一個有效的HTML檔案,因此正則表示式不需要排除那些無效的標籤。
所以如果是在兩個尖括號之間的內容,就應該是一個HTML標籤。
許多正則表示式的新手會首先想到用正則表示式 < <<. > > > ,他們會很驚訝的發現,對於測試字串,
“This is a <EM> first </EM> test”,
(說明:<. > 第一個"<"表示第一字元為"<",第二個"."表示的是任意單個字元,第三個" "表示的是前面字元重複一次或多次,第四個">"表示最後是">"字元)
你可能期望會返回 <EM> ,然後繼續進行匹配的時候,返回 </EM> 。但事實是不會。
正則表示式將會匹配“ <EM> first </EM> ”。
很顯然這不是我們想要的結果。原因在於“ ”是貪婪的。也就是說,“ ”會導致正則表示式引擎試圖儘可能的重複前導字元。
(儘量貪婪地匹配最後一個>)
只有當這種重複會引起整個正則表示式匹配失敗的情況下,引擎會進行回溯。
也就是說,它會放棄最後一次的“重複”,然後處理正則表示式餘下的部分。
和“ ”類似,“?*”的重複也是貪婪的。(word的萬用字元不是貪婪的)
深入正則表示式引擎內部
讓我們來看看正則引擎如何匹配前面的例子。
第一個記號是“ <”,這是一個文字元號。第二個符號是“.”,匹配了字元“E”,然後“ ”一直可以匹配其餘的字元,直到一行的結束。
然後到了換行符,匹配失敗(“.”不匹配換行符)。於是引擎開始對下一個正則表示式符號進行匹配。也即試圖匹配“> ”。
到目前為止,“ <. ”已經匹配了“ <EM> first </EM> test”。引擎會試圖將“> ”與換行符進行匹配,結果失敗了。於是引擎進行回溯。
結果是現在“ <. ”匹配“ <EM> first </EM> tes”。於是引擎將“> ”與“t”進行匹配。顯然還是會失敗。
這個過程繼續,直到“ <. ”匹配“ <EM> first </EM”,“> ”與“> ”匹配。於是引擎找到了一個匹配“ <EM> first </EM> ”。
記住,正則導向的引擎是“急切的”,所以它會急著報告它找到的第一個匹配。而不是繼續回溯,即使可能會有更好的匹配,例如“ <EM> ”。
所以我們可以看到,由於“ ”的貪婪性,使得正則表示式引擎返回了一個最左邊的最長的匹配(即匹配"<EM> first </EM>",而不是匹配"<EM>")。
用懶惰性取代貪婪性
一個用於修正以上問題的可能方案是用“ ”的惰性代替貪婪性。你可以在“ ”後面緊跟一個問號“?”來達到這一點。
“*”,“{}”和“?”表示的重複也可以用這個方案。因此在上面的例子中我們可以使用“ <. ?> ”。
讓我們再來看看正則表示式引擎的處理過程。
“This is a <EM> first </EM> test”, <. >
再一次,正則表示式記號“ <”會匹配字串的第一個“ <”。下一個正則記號是“.”。這次是一個懶惰的“ ”來重複上一個字元。
這告訴正則引擎,儘可能少的重複上一個字元。因此引擎匹配“.”和字元“E”,然後用“> ”匹配“M”,結果失敗了。
引擎會進行回溯,和上一個例子不同,因為是惰性重複,所以引擎是擴充套件惰性重複而不是減少,於是“ <. ”現在被擴充套件為“ <EM”。引擎繼續匹配下一個記號“> ”。
這次得到了一個成功匹配。引擎於是報告“ <EM> ”是一個成功的匹配。整個過程大致如此。
惰性擴充套件的一個替代方案我們還有一個更好的替代方案。可以用一個貪婪重複與一個取反字符集:“ <[^> ] > ”。
之所以說這是一個更好的方案在於使用惰性重複時,引擎會在找到一個成功匹配前對每一個字元進行回溯。而使用取反字符集則不需要進行回溯。
最後要記住的是,本教程僅僅談到的是正則導向的引擎。
文字導向的引擎是不回溯的。但是同時他們也不支援惰性重複操作。
7.使用“.”匹配幾乎任意字元
在正則表示式中,“.”是最常用的符號之一。不幸的是,它也是最容易被誤用的符號之一。
“.”匹配一個單個的字元而不用關心被匹配的字元是什麼。唯一的例外是新行符。
在本教程中談到的引擎,預設情況下都是不匹配新行符的。
因此在預設情況下,“.”等於是字符集[^\n\r](Window)或[^\n](Unix)的簡寫。
這個例外是因為歷史的原因。因為早期使用正則表示式的工具是基於行的。
它們都是一行一行的讀入一個檔案,將正則表示式分別應用到每一行上去。
在這些工具中,字串是不包含新行符的。因此“.”也就從不匹配新行符。
現代的工具和語言能夠將正則表示式應用到很大的字串甚至整個檔案上去。
本教程討論的所有正則表示式實現都提供一個選項,可以使“.”匹配所有的字元,包括新行符。
在RegexBuddy,EditPadPro或PowerGREP等工具中,你可以簡單的選中“點號匹配新行符”。
在Perl中,“.”可以匹配新行符的模式被稱作“單行模式”。很不幸,這是一個很容易混淆的名詞。
因為還有所謂“多行模式”。多行模式隻影響行首行尾的錨定(anchor),而單行模式隻影響“.”。
其他語言和正則表示式庫也採用了Perl的術語定義。
當在.NETFramework中使用正則表示式類時,你可以用類似下面的語句來啟用單行模式:
Regex.Match(“string”,”regex”,RegexOptions.SingleLine)
保守的使用點號“.”
點號可以說是最強大的元字元。它允許你偷懶:用一個點號,就能匹配幾乎所有的字元。
但是問題在於,它也常常會匹配不該匹配的字元。我會以一個簡單的例子來說明。
讓我們看看如何匹配一個具有“mm/dd/yy”格式的日期,但是我們想允許使用者來選擇分隔符。
很快能想到的一個方案是 < <\d\d.\d\d.\d\d> > 。
看上去它能匹配日期“02/12/03”。問題在於02512703也會被認為是一個有效的日期。
< <\d\d[-/.]\d\d[-/.]\d\d> > 看上去是一個好一點的解決方案。記住點號在一個字符集裡不是元字元。這個方案遠不夠完善,它會匹配“99/99/99”。
而 < <[0-1]\d[-/.][0-3]\d[-/.]\d\d> > 又更進一步。儘管他也會匹配“19/39/99”。
你想要你的正則表示式達到如何完美的程度取決於你想達到什麼樣的目的。如果你想校驗使用者輸入,則需要儘可能的完美。
如果你只是想分析一個已知的源,並且我們知道沒有錯誤的資料,用一個比較好的正則表示式來匹配你想要搜尋的字元就已經足夠。
8.字串開始和結束的錨定
錨定和一般的正則表示式符號不同,它不匹配任何字元。相反,他們匹配的是字元之前或之後的位置。
(錨定:就是指定位置、定位。表明在什麼位置,如:單詞首位置還是單詞尾的位置等等。word中圖片的位置也有錨定的概念,就是定點陣圖片位置。)
“^”匹配一行字串第一個字元前的位置。
< <^a> > 將會匹配字串“abc”中的a。
< <^b> > 將不會匹配“abc”中的任何字元。
類似的,$匹配字串中最後一個字元的後面的位置。所以
< <c$> > 匹配“abc”中的c。
錨定的應用在程式語言中校驗使用者輸入時,使用錨定是非常重要的。
如果你想校驗使用者的輸入為整數,用 < <^\d $> > 。
使用者輸入中,常常會有多餘的前導空格或結束空格。你可以用
< <^\s*> > 和 < <\s*$> > 來匹配前導空格或結束空格。
使用“^”和“$”作為行的開始和結束錨定
如果你有一個包含了多行的字串。例如:“firstline\n\rsecondline”(其中\n\r表示一個新行符)。
常常需要對每行分別處理而不是整個字串。因此,幾乎所有的正則表示式引擎都提供一個選項,可以擴充套件這兩種錨定的含義。
“^”可以匹配字串的開始位置(在f之前),以及每一個新行符的後面位置(在\n\r和s之間)。
類似的,$會匹配字串的結束位置(最後一個e之後),以及每個新行符的前面(在e與\n\r之間)。
在.NET中,當你使用如下程式碼時,將會定義錨定匹配每一個新行符的前面和後面位置:
Regex.Match("string","regex",RegexOptions.Multiline)
應用:stringstr=Regex.Replace(Original,"^","> ",RegexOptions.Multiline)--將會在每行的行首插入“> ”。
絕對錨定 < <\A> > 只匹配整個字串的開始位置, < <\Z> > 只匹配整個字串的結束位置。
即使你使用了“多行模式”, < <\A> > 和 < <\Z> > 也從不匹配新行符。
即使\Z和$只匹配字串的結束位置,仍然有一個例外的情況。
如果字串以新行符結束,則\Z和$將會匹配新行符前面的位置,而不是整個字串的最後面。
這個“改進”是由Perl引進的,然後被許多的正則表示式實現所遵循,包括Java,.NET等。
如果應用 < <^[a-z] $> > 到“joe\n”,則匹配結果是“joe”而不是“joe\n”。
在本文中講述了正則表示式中的組與向後引用,先前向後檢視,條件測試,單詞邊界,選擇符等表示式及例子,並分析了正則引擎在執行匹配時的內部機理。
9.單詞邊界
元字元 < <\b> > 也是一種對位置進行匹配的“錨”。這種匹配是0長度匹配。
有4種位置被認為是“單詞邊界”:
1)在字串的第一個字元前的位置(如果字串的第一個字元是一個“單詞字元”)
2)在字串的最後一個字元後的位置(如果字串的最後一個字元是一個“單詞字元”)
3)在一個“單詞字元”和“非單詞字元”之間,其中“非單詞字元”緊跟在“單詞字元”之後
4)在一個“非單詞字元”和“單詞字元”之間,其中“單詞字元”緊跟在“非單詞字元”後面
“單詞字元”是可以用“\w”匹配的字元,“非單詞字元”是可以用“\W”匹配的字元。
在大多數的正則表示式實現中,“單詞字元”通常包括 < <[a-zA-Z0-9_]> > 。例如:
< <\b4\b> >
能夠匹配單個的4而不是一個更大數的一部分。這個正則表示式不會匹配“44”中的4。
換種說法,幾乎可以說 < <\b> > 匹配一個“字母數字序列”的開始和結束的位置。
“單詞邊界”的取反集為 < <\B> > ,他要匹配的位置是兩個“單詞字元”之間或者兩個“非單詞字元”之間的位置。
深入正則表示式引擎內部
讓我們看看把正則表示式 < <\bis\b> > 應用到字串
“This island is beautiful”。
引擎先處理符號 < <\b> > 。因為\b是0長度,所以第一個字元T前面的位置會被考察。
因為T是一個“單詞字元”,而它前面的字元是一個空字元(void),所以\b匹配了單詞邊界。接著 < <i> > 和第一個字元“T”匹配失敗。
匹配過程繼續進行,直到第五個空格符,和第四個字元“s”之間又匹配了 < <\b> > 。然而空格符和 < <i> > 不匹配。
繼續向後,到了第六個字元“i”,和第五個空格字元之間匹配了 < <\b> > ,然後 < <is> > 和第六、第七個字元都匹配了。
然而第八個字元和第二個“單詞邊界”不匹配,所以匹配又失敗了。
到了第13個字元i,因為和前面一個空格符形成“單詞邊界”,同時 < <is> > 和“is”匹配。引擎接著嘗試匹配第二個 < <\b> > 。
因為第15個空格符和“s”形成單詞邊界,所以匹配成功。引擎“急著”返回成功匹配的結果。
相關推薦
vb.net正則表示式快速入門(2)
6.使用?*或 進行重複?:告訴引擎匹配前導字元0次或一次。事實上是表示前導字元是可選的。(問號) :告訴引擎匹配前導字元1次或多次(空格)*:告訴引擎匹配前導字元0次或多次(星號) <[A-Za-z][A-Za-z0-9]*> 匹配沒有屬性的HTML標籤,“ <”以及“>
vb.net正則表示式快速入門(1)
深入淺出之正則表示式 作者:lzmtw 注:JanGoyvaerts為RegexBuddy寫的教程的譯文 前言:半年前我對正則表示式產生了興趣,在網上查詢過不少資料,看過不少的教程,最後在使用一個正則表示式工具RegexBuddy時發現他的教程寫的非常好,可以說是我目前見過最好的正則表示式
vb.net正則表示式快速入門(3)完
作者:lzmtw 10.選擇符正則表示式中“ ¦”表示選擇。 你可以用選擇符匹配多個可能的正則表示式中的一個。如果你想搜尋文字“cat”或“dog”,你可以用 < <cat¦dog> > 。 如果你想有更多的選擇,你只要擴充套件列表 <
爬蟲入門系列(五):正則表示式完全指南(上)
爬蟲入門系列目錄: 正則表示式處理文字有如疾風掃秋葉,絕大部分程式語言都內建支援正則表示式,它應用在諸如表單驗證、文字提取、替換等場景。爬蟲系統更是離不開正則表示式,用好正則表示式往往能收到事半功倍的效果。 介紹正則表示式前,先來看一個問題,下面這段文字來自豆瓣的某個網頁連結,我對內容
爬蟲入門系列(六):正則表示式完全指南(下)
爬蟲入門系列目錄: 正則表示式是一種更為強大的字串匹配、字串查詢、字串替換等操作工具。上篇講解了正則表示式的基本概念和語法以及re模組的基本使用方式,這節來詳細說說 re 模組作為 Python 正則表示式引擎提供了哪些便利性操作。 >>> import re
正則表示式快速入門
在說正則表示式前先看一道題: 問題描述: 在給定字串中找出單詞 ( “單詞”由大寫字母和小寫字母字元構成,其他非字母字元視為單詞的間隔, 如空格、問號、數字等等;另外單個字母不算單詞);找到單詞後,按照長度進行降序排序, (排序時如果長度相同,則按
正則表示式快速入門教程
由於評論裡有過長的URL,所以本頁排版比較混亂,推薦你到原處檢視,看完了如果有問題,再到這裡來提出.一些要說的話:如果你沒有正則表示式的基礎,請跟著教程“一步步來”。請不要大概地掃兩眼就說看不懂——以這種態度我寫成什麼樣你也看不懂。當我告訴你這是“30分鐘入門教程”時,請不要試圖在30秒內入門。事實是,我身邊
C#正則表示式快速入門
[介紹] 作者將自己在學習正則表示式中的心得和筆記作了個總結性文章,希望對初學C#正則表示式的讀者有幫助。[內容]什麼是正則表示式涉及的基本的類正則表示式基礎知識構建表示式基本方法編寫一個檢驗程式參考資料[正文] 對於初學者看到類似“/[email pr
正則表示式學習筆記(一)
開始和結束 ^ $ '^' 表示開始 例如:'^the' 表示以 the 開頭的詞 '$' 表示結束 例如:'the$' 表示以 the 結尾的詞 'the' 表示 包含 the 的詞
正則表示式並不難(轉)
對於正則表示式,相信很多人都知道,但是很多人的第一感覺就是難學,因為看第一眼時,覺得完全沒有規律可尋,而且全是一堆各種各樣的特殊符號,完全不知所云。 其實只是對正則不瞭解而以,瞭解了你就會發現,原來就這樣啊正則所用的相關字元其實不多,也不難記,更不難懂,唯一難的就是組合起來之後,可讀性比較差,而
python正則表示式詳解(二):特殊字元序列
內容提要: 說明:僅供學習交流使用 二、python正則表示式中的特殊字元序列 \number \A \Z \b \B \d \D \s \S \w \W \\ 2.1\number 以相同的序號代表的組所匹配的內容
Python爬蟲之正則表示式的使用(三)
import re html = ''' <div class="slide-page" style="width: 700px;" data-index="1"> <a class="item" target="_blank" href="https:
Thymeleaf 快速入門(2)簡單表示式
2.1.1變量表達式:${…} 模板名稱:var.html 原理類似OGNL/SpringEL表示式 e.g. 1. Established locale country: <span th:text="${#locale.country}"
正則表示式 進階(一)-- 匹配多連續字元、位置匹配、子表示式使用
之前一篇博文正則表示式 入門講了下正則表示式的一些基本使用,這次講一下高階的。還是那句話,要多用,才能夠記住並留在你的大腦皮層。 1. 匹配一個或多個連續字元 用+符號, a+,意思是匹配1個或多個
正則表示式 轉義字元(轉)
字元匹配語法: \d 匹配數字(0~9) ‘\d’匹配8,不匹配12; \D 匹配非數字 ‘\D’匹配c,不匹配3; \w 匹配任意單字元 ‘\w\w’ 匹配A3,不匹配@3; \W 匹配非單字元 ‘\W’匹配@,不匹配c; \s 匹配空白字元 ‘\d\
正則表示式 進階(二)-- 回溯引用、前後查詢、嵌入條件
回溯引用是指模式的後半部分引用在前半部分中定義的子表示式 回溯引用只能用來引用模式裡的子表示式 下面是一個回溯引用的例子 只能匹配H1 第8行是不合法的 第8行被成功的排除掉了。 \1 \2
正則表示式學習程序(一)re.match()
#正則表示式學習筆記 import re """ .匹配任意字元 除換行符 {n}精確匹配前面n個表示式 \s 匹配任意的空白字元 \w 匹配字母數字及下劃線 .* 匹配任意除換行符之外的字元 {n} 精確匹配n個前面表示式。 + 匹配1個或多個的表示式。 ( )
正則表示式進行篩選(轉載)
從各個網站查詢最後總結符合自己的專案: // 用來取<div style="line-height:20px;font-size:10pt">內容</div> 中間的內容 String rgex="(?<=<[D,d][I,i
re2正則表示式引擎學習(五)
改寫為DFA匹配時的執行過程。 首先打印出來的是NFA的結構,然後將NFA的結構轉化為DFA的結構,構建對應的DFA轉移矩陣。然後根據轉移矩陣進行匹配 執行時,正則表示式為ab*c|d,匹配的字串為d ab*c|d 9. alt -> 6 | 8 6. alt -&
正則表示式-重複匹配(二)
在前面一章中,講了元字元的使用,前面沒有明確說明,那就是每個元字元匹配一個字元,也就是說[\d]匹配任意一個數字。那麼假設我想匹配三位數字怎麼辦,當然可以寫成 \d\d\d 這種形式,但是要是我想匹配10位數字呢,豈不是要寫10次\d。這樣寫當然