正則表達式

正則表達式

計算機科學的一個概念
正則表達式,又稱正規表示法、常規表示法(英語:RegularExpression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器裡,正則表達式通常被用來檢索、替換那些符合某個模式的文本。許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就内建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達式通常縮寫成“regex”,單數有regexp、regex,複數有regexps、regexes、regexen。為解決CAN網絡下DBC(Database CAN)協議數據解析和結構表征問題,通過正則表達式解析了DBC文件協議信息,利用多叉樹結構,對CAN網絡協議信息進行結構表征。針對Intel和Motorola不同格式下的協議解析問題,提出了報文數據場的信号色塊表示方法以及起始位轉換公式。[1]
    中文名:正則表達式 外文名:Regular Expression 别名:規則表達式 代碼簡寫:regex、regexp或RE 行業歸屬:計算機科學 作用:用來檢索、替換那些符合某個模式(規則)的文本

起源

正則表達式的“鼻祖”或許可一直追溯到科學家對人類神經系統工作原理的早期研究。美國新澤西州的WarrenMcCulloch和出生在美國底特律的WalterPitts這兩位神經生理方面的科學家,研究出了一種用數學方式來描述神經網絡的新方法,他們創造性地将神經系統中的神經元描述成了小而簡單的自動控制元,從而作出了一項偉大的工作革新。

在1956年,出生在被馬克·吐溫(MarkTwain)稱為“美國最美麗的城市之一”的哈特福德市的一位名叫StephenKleene的數學科學家,他在WarrenMcCulloch和WalterPitts早期工作的基礎之上,發表了一篇題目是《神經網事件的表示法》的論文,利用稱之為正則集合的數學符号來描述此模型,引入了正則表達式的概念。正則表達式被作為用來描述其稱之為“正則集的代數”的一種表達式,因而采用了“正則表達式”這個術語。

之後一段時間,人們發現可以将這一工作成果應用于其他方面。KenThompson就把這一成果應用于計算搜索算法的一些早期研究,KenThompson是Unix的主要發明人,也就是大名鼎鼎的Unix之父。Unix之父将此符号系統引入編輯器QED,然後是Unix上的編輯器ed,并最終引入grep。JeffreyFriedl在其着作《MasteringRegularexpressions(2ndedition)》(中文版譯作:精通正則表達式,已出到第三版)中對此作了進一步闡述講解,如果你希望更多了解正則表達式理論和曆史,推薦你看看這本書。

自此以後,正則表達式被廣泛地應用到各種UNIX或類似于UNIX的工具中,如大家熟知的Perl。Perl的正則表達式源自于HenrySpencer編寫的regex,之後已演化成了pcre(Perl兼容正則表達式PerlCompatibleRegularExpressions),pcre是一個由PhilipHazel開發的、為很多現代工具所使用的庫。正則表達式的第一個實用應用程序即為Unix中的qed編輯器。

然後,正則表達式在各種計算機語言或各種應用領域得到了廣大的應用和發展,演變成為計算機技術森林中的一隻形神美麗且聲音動聽的百靈鳥。

以上是關于正則表達式的起源和發展的曆史描述,如今正則表達式在基于文本的編輯器和搜索工具中依然占據着一個非常重要的地位。

在最近的六十年中,正則表達式逐漸從模糊而深奧的數學概念,發展成為在計算機各類工具和軟件包應用中的主要功能。不僅僅衆多UNIX工具支持正則表達式,近二十年來,在WINDOWS的陣營下,正則表達式的思想和應用在大部分Windows開發者工具包中得到支持和嵌入應用!從正則式在MicrosoftVisualBasic6或MicrosoftVBScript到.NETFramework中的探索和發展,WINDOWS系列産品對正則表達式的支持發展到無與倫比的高度,幾乎所有Microsoft開發者和所有.NET語言都可以使用正則表達式。如果你是一位接觸計算機語言的工作者,那麼你會在主流操作系統(*nix[Linux,Unix等]、Windows、HP、BeOS等)、主流的開發語言(delphi、Scala、PHP、C#、Java、C++、Objective-c、Swift、VB、Javascript、Ruby以及Python等)、數以億萬計的各種應用軟件中,都可以看到正則表達式優美的舞姿。

概念

正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字符串”,這個“規則字符串”用來表達對字符串的一種過濾邏輯。

給定一個正則表達式和另一個字符串,我們可以達到如下的目的:

1.給定的字符串是否符合正則表達式的過濾邏輯(稱作“匹配”);

2.可以通過正則表達式,從字符串中獲取我們想要的特定部分。

正則表達式的特點是:

1.靈活性、邏輯性和功能性非常的強;

2.可以迅速地用極簡單的方式達到字符串的複雜控制。

3.對于剛接觸的人來說,比較晦澀難懂。

由于正則表達式主要應用對象是文本,因此它在各種文本編輯器場合都有應用,小到著名編輯器EditPlus,大到MicrosoftWord、VisualStudio等大型編輯器,都可以使用正則表達式來處理文本内容。

引擎分類

正則引擎主要可以分為兩大類:一種是DFA,一種是NFA。這兩種引擎都有了很久的曆史(至今二十多年),當中也由這兩種引擎産生了很多變體!于是POSIX的出台産生規範了不必要變體的繼續産生。這樣一來,主流的正則引擎又分為3類:一、DFA,二、傳統型NFA,三、POSIXNFA。

DFA引擎在線性時狀态下執行,因為它們不要求回溯(并因此它們永遠不測試相同的字符兩次)。DFA引擎還可以确保匹配最長的可能的字符串。但是,因為DFA引擎隻包含有限的狀态,所以它不能匹配具有反向引用的模式;并且因為它不構造顯示擴展,所以它不可以捕獲子表達式。

傳統的NFA引擎運行所謂的“貪婪的”匹配回溯算法,以指定順序測試正則表達式的所有可能的擴展并接受第一個匹配項。因為傳統的NFA構造正則表達式的特定擴展以獲得成功的匹配,所以它可以捕獲子表達式匹配和匹配的反向引用。但是,因為傳統的NFA回溯,所以它可以訪問完全相同的狀态多次(如果通過不同的路徑到達該狀态)。因此,在最壞情況下,它的執行速度可能非常慢。因為傳統的NFA接受它找到的第一個匹配,所以它還可能會導緻其他(可能更長)匹配未被發現。

POSIXNFA引擎與傳統的NFA引擎類似,不同的一點在于:在它們可以确保已找到了可能的最長的匹配之前,它們将繼續回溯。因此,POSIXNFA引擎的速度慢于傳統的NFA引擎;并且在使用POSIXNFA時,您恐怕不會願意在更改回溯搜索的順序的情況下來支持較短的匹配搜索,而非較長的匹配搜索。

使用DFA引擎的程序主要有:awk,egrep,flex,lex,MySQL,Procmail等;

使用傳統型NFA引擎的程序主要有:GNUEmacs,Java,ergp,less,more,.NET語言,PCRElibrary,Perl,PHP,Python,Ruby,sed,vi;

使用POSIXNFA引擎的程序主要有:mawk,MorticeKernSystems’utilities,GNUEmacs(使用時可以明确指定);

也有使用DFA/NFA混合的引擎:GNUawk,GNUgrep/egrep,Tcl。

舉例簡單說明NFA與DFA工作的區别:

比如有字符串thisisyansen’sblog,正則表達式為/ya(msen|nsen|nsem)/(不要在乎表達式怎麼樣,這裡隻是為了說明引擎間的工作區别)。NFA工作方式如下,先在字符串中查找y然後匹配其後是否為a,如果是a則繼續,查找其後是否為m如果不是則匹配其後是否為n(此時淘汰msen選擇支)。然後繼續看其後是否依次為s,e,接着測試是否為n,是n則匹配成功,不是則測試是否為m。為什麼是m?因為NFA工作方式是以正則表達式為标準,反複測試字符串,這樣同樣一個字符串有可能被反複測試了很多次!

而DFA則不是如此,DFA會從this中t開始依次查找y,定位到y,已知其後為a,則查看表達式是否有a,此處正好有a。然後字符串a後為n,DFA依次測試表達式,此時msen不符合要求淘汰。nsen和nsem符合要求,然後DFA依次檢查字符串,檢測到sen中的n時隻有nsen分支符合,則匹配成功!

由此可以看出來,兩種引擎的工作方式完全不同,一個(NFA)以表達式為主導,一個(DFA)以文本為主導!一般而論,DFA引擎則搜索更快一些!但是NFA以表達式為主導,反而更容易操縱,因此一般程序員更偏愛NFA引擎!兩種引擎各有所長,而真正的引用則取決與你的需要以及所使用的語言!

符号

(摘自《正則表達式之道》)

正則表達式

由一些普通字符和一些元字符(metacharacters)組成。普通字符包括大小寫的字母和數字,而元字符則具有特殊的含義,我們下面會給予解釋。

在最簡單的情況下,一個正則表達式看上去就是一個普通的查找串。例如,正則表達式"testing"中沒有包含任何元字符,它可以匹配"testing"和"testing123"等字符串,但是不能匹配"Testing"。

要想真正的用好正則表達式,正确的理解元字符是最重要的事情。

最簡單的元字符是點,它能夠匹配任何單個字符(注意不包括換行符)。假定有個文件test.txt包含以下幾行内容:

heisarat

heisinarut

thefoodisRotten

Ilikerootbeer

我們可以使用grep命令來測試我們的正則表達式,grep命令使用正則表達式去嘗試匹配指定文件的每一行,并将至少有一處匹配表達式的所有行顯示出來。命令grepr.ttest.txt。

在test.txt文件中的每一行中搜索正則表達式r.t,并打印輸出匹配的行。正則表達式r.t匹配一個r接着任何一個字符再接着一個t。所以它将匹配文件中的rat和rut,而不能匹配Rotten中的Rot,因為正則表達式是大小寫敏感的。要想同時匹配大寫和小寫字母,應該使用字符區間元字符(方括号)。正則表達式[Rr]能夠同時匹配R和r。所以,要想匹配一個大寫或者小寫的r接着任何一個字符再接着一個t就要使用這個表達式:[Rr].t。

要想匹配行首的字符要使用抑揚字符(^)——有時也被叫做插入符。例如,想找到text.txt中行首"he"打頭的行,你可能會先用簡單表達式he,但是這會匹配第三行的the,所以要使用正則表達式^he,它隻匹配在行首出現的h。

有時候指定“除了×××都匹配”會比較容易達到目的,當抑揚字符(^)出方括号中時,它表示“排除”,例如要匹配he,但是排除前面是tors的情形(也就是the和she),可以使用:[^st]he。

可以使用方括号來指定多個字符區間。例如正則表達式[A-Za-z]匹配任何字母,包括大寫和小寫的;正則表達式[A-Za-z][A-Za-z]*匹配一個字母後面接着0或者多個字母(大寫或者小寫)。當然我們也可以用元字符+做到同樣的事情,也就是:[A-Za-z]+,和[A-Za-z][A-Za-z]*完全等價。但是要注意元字符+并不是所有支持正則表達式的程序都支持的。關于這一點可以參考後面的正則表達式語法支持情況。

要指定特定數量的匹配,要使用大括号(注意必須使用反斜杠來轉義)。想匹配所有10和100的實例而排除1和1000,可以使用:10{1,2},這個正則表達式匹配數字1後面跟着1或者2個0的模式。在這個元字符的使用中一個有用的變化是忽略第二個數字,例如正則表達式0{3,}将匹配至少3個連續的0。

例1

将所有方法foo(a,b,c)的實例改為foo(b,a,c)。這裡a、b和c可以是任何提供給方法foo()的參數。也就是說我們要實現這樣的轉換:

之前之後

foo(10,7,2)foo(7,10,2)

foo(x+13,y-2,10)foo(y-2,x+13,10)

foo(bar(8),x+y+z,5)foo(x+y+z,bar(8),5)

下面這條替換命令能夠實現這一魔法:

:%s/foo(([^,]*),([^,]*),([^,)]*))/foo(2,1,3)/g

讓我們把它打散來加以分析。寫出這個表達式的基本思路是找出foo()和它的括号中的三個參數的位置。第一個參數是用這個表達式來識别的::([^,]*),我們可以從裡向外來分析它:

[^,]除了逗号之外的任何字符

[^,]*0或者多個非逗号字符

([^,]*)将這些非逗号字符标記為1,這樣可以在之後的替換模式表達式中引用它

([^,]*),我們必須找到0或者多個非逗号字符後面跟着一個逗号,并且非逗号字符那部分要标記出來以備後用。

正是指出一個使用正則表達式常見錯誤的最佳時機。為什麼我們要使用[^,]*這樣的一個表達式,而不是更加簡單直接的寫法,例如:.*,來匹配第一個參數呢?設想我們使用模式.*來匹配字符串"10,7,2",它應該匹配"10,"還是"10,7,"?為了解決這個兩義性(ambiguity),正則表達式規定一律按照最長的串來,在上面的例子中就是"10,7,",顯然這樣就找出了兩個參數而不是我們期望的一個。所以,我們要使用[^,]*來強制取出第一個逗号之前的部分。

這個表達式我們已經分析到了:foo(([^,]*),這一段可以簡單的翻譯為“當你找到foo(就把其後直到第一個逗号之前的部分标記為1”。然後我們使用同樣的辦法标記第二個參數為2。對第三個參數的标記方法也是一樣,隻是我們要搜索所有的字符直到右括号。我們并沒有必要去搜索第三個參數,因為我們不需要調整它的位置,但是這樣的模式能夠保證我們隻去替換那些有三個參數的foo()方法調用,在foo()是一個重載(overloading)方法時這種明确的模式往往是比較保險的。然後,在替換部分,我們找到foo()的對應實例,然後利用标記好的部分進行替換,是把第一和第二個參數交換位置。

替換技巧

實例目錄

【1】正則表達式應用——替換指定内容到行尾

【2】正則表達式應用——數字替換

【3】正則表達式應用——删除每一行行尾的指定字符

【4】正則表達式應用——替換帶有半角括号的多行

【5】正則表達式應用——删除空行

【6】正則表達式應用——實例應用

應用實例

【1】正則表達式應用——替換指定内容到行尾

原始文本如下面兩行

abcaaaaa

123abc444

希望每次遇到“abc”,則替換“abc”以及其後到行尾的内容為“abcefg”

即上面的文本最終替換為:

abcefg

123abcefg

解決:

①在替換對話框,查找内容裡輸入“abc.*”,替換内容輸入為“abcefg”

②同時勾選“正則表達式”複選框,然後點擊“全部替換”按鈕

其中,符号的含義如下:

“.”=匹配任意字符

“*”=匹配0次或更多

注意:其實就是正則表達式替換,這裡隻是把一些曾經提出的問題加以整理,單純從正則表達式本身來說,就可以引申出成千上萬種特例。

【2】正則表達式應用——數字替換

希望把

asdadas123asdasdas456asdasdasd789asdasd

替換為:

asdadasasdasdasasdasdasdasdasd

在替換對話框裡面,勾選“正則表達式”複選框;

在查找内容裡面輸入“([0-9])([0-9])([0-9])”,不含引号

“替換為:”裡面輸入“[123]”,不含引号

####備注####:查找([0-9]+)替換:[1]更簡單通用些

範圍為你所操作的範圍,然後選擇替換即可。

實際上這也是正則表達式的使用特例,“[0-9]”表示匹配0~9之間的任何特例,同樣“[a-z]”就表示匹配a~z之間的任何特例

上面重複使用了“[0-9]”,表示連續出現的三個數字

括号用來選擇原型,進行分組,替換時要用

“1”代表第一個“[0-9]”對應的原型,“2”代表第二個“[0-9]”對應的原型,依此類推

“[”、“]”為單純的字符,表示添加“[”或“]”,如果輸入“其它123其它”,則替換結果為:

asdadas其它123其它asdasdas其它456其它asdasdasd其它789其它asdasd

功能增強:

如果将查找内容“[0-9][0-9][0-9]”改為“[0-9]*[0-9]”,對應1或123或12345或...

大家根據需要定制

相關内容還有很多,可以自己參考正則表達式的語法仔細研究一下

【3】正則表達式應用——删除每一行行尾的指定字符

因為這幾個字符在行中也是出現的,所以肯定不能用簡單的替換實現

比如

123451265345

2345

需要删除每行末尾的“345”

這個也算正則表達式的用法,其實仔細看正則表達式應該比較簡單,不過既然有這個問題提出,說明對正則表達式還得有個認識過程,解決方法如下

解決:

在替換對話框中,啟用“正則表達式”複選框

在查找内容裡面輸入“345$”

這裡“$”表示從行尾匹配

如果從行首匹配,可以用“^”來實現,不過EditPlus有另一個功能可以很簡單的删除行首的字符串

a.選擇要操作的行

b.編輯-格式-删除行注釋

c.在彈出對話框裡面輸入要清除的行首字符,确定

【4】正則表達式應用——替換帶有半角括号的多行

幾百個網頁中都有下面一段代碼:

<!--

htmlAdWH('93163607','728','90');

//-->

我想把它們都去掉,可是找了很多search&replace的軟件,都是隻能對“一行”進行操作。

EditPlus打開幾百個網頁文件還是比較順暢的,所以完全可以勝任這個工作。

具體解決方法,在Editplus中使用正則表達式,由于“(”、“)”被用做預設表達式(或者可以稱作子表達式)的标志,所以查找

“n”

時會提示查找不到,所以也就無法進行替換了,這時可以把“(”、“)”使用任意字符标記替代,即半角句号:“.”。替換内容為

n

在替換對話框啟用“正則表達式”選項,這時就可以完成替換了

補充:

對()這樣的特殊符号,應該用()來表示,這也是很标準的regexp語法,可以寫為

n

【5】正則表達式應用——删除空行

啟動EditPlus,打開待處理的文本類型文件。

①、選擇“查找”菜單的“替換”命令,彈出文本替換對話框。選中“正則表達式”複選框,表明我們要在查找、替換中使用正則表達式。然後,選中“替換範圍”中的“當前文件”,表明對當前文件操作。

②、單擊“查找内容”組合框右側的按鈕,出現下拉菜單。

③、下面的操作添加正則表達式,該表達式代表待查找的空行。(技巧提示:空行僅包括空格符、制表符、回車符,且必須以這三個符号之一作為一行的開頭,并且以回車符結尾,查找空行的關鍵是構造代表空行的正則表達式)。

直接在“查找“中輸入正則表達式“^[t]*n”,注意t前有空格符。

(1)選擇“從行首開始匹配”,“查找内容”組合框中出現字符“^”,表示待查找字符串必須出文本中一行的行首。

(2)選擇“字符在範圍中”,那麼在“^”後會增加一對括号“[]”,當前插入點在括号中。括号在正則表達式中表示,文本中的字符匹配括号中任意一個字符即符合查找條件。

(3)按一下空格鍵,添加空格符。空格符是空行的一個組成成分。

(4)選擇“制表符”,添加代表制表符的“t”。

(5)移動光标,将當前插入點移到“]”之後,然後選擇“匹配0次或更多”,該操作會添加星号字符“*”。星号表示,其前面的括号“[]”内的空格符或制表符,在一行中出現0個或多個。

(6)選擇“換行符”,插入“n”,表示回車符。

④、“替換為”組合框保持空,表示删除查找到的内容。單擊“替換”按鈕逐個行删除空行,或單擊“全部替換”按鈕删除全部空行(注意:EditPlus有時存在“全部替換”不能一次性完全删除空行的問題,可能是程序BUG,需要多按幾次按鈕)。

【6】正則表達式應用——實例應用

1.驗證用戶名和密碼:(“^[a-zA-Z]w{5,15}$“)正确格式:“[A-Z][a-z]_[0-9]“組成,并且第一個字必須為字母6~16位;

2.驗證電話号碼:(“^(d{3.4}-)d{7,8}$“)正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;

3.驗證手機号碼:“^1[3|4|5|8][0-9]d{8}$“;

4.驗證身份證号(15位或18位數字):“d{17}[[0-9],0-9xX]“;

5.驗證Email地址:(“^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$“);

6.隻能輸入由數字和26個英文字母組成的字符串:(“^[A-Za-z0-9]+$“);

7.整數或者小數:^[0-9]+.{0,1}[0-9]{0,2}$

8.隻能輸入數字:“^[0-9]*$“。

9.隻能輸入n位的數字:“^d{n}$“。

10.隻能輸入至少n位的數字:“^d{n,}$“。

11.隻能輸入m~n位的數字:“^d{m,n}$“。

12.隻能輸入零和非零開頭的數字:“^(0|[1-9][0-9]*)$“。

13.隻能輸入有兩位小數的正實數:“^[0-9]+(.[0-9]{2})?$“。

14.隻能輸入有1~3位小數的正實數:“^[0-9]+(.[0-9]{1,3})?$“。

15.隻能輸入非零的正整數:“^+?[1-9][0-9]*$“。

16.隻能輸入非零的負整數:“^-[1-9][]0-9“*$。

17.隻能輸入長度為3的字符:“^.{3}$“。

18.隻能輸入由26個英文字母組成的字符串:“^[A-Za-z]+$“。

19.隻能輸入由26個大寫英文字母組成的字符串:“^[A-Z]+$“。

20.隻能輸入由26個小寫英文字母組成的字符串:“^[a-z]+$“。

21.驗證是否含有^%&',;=?$“等字符:“[^%&',;=?$x22]+“。

22.隻能輸入漢字:“^[u4e00-u9fa5]{0,}$“。

23.驗證URL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$“。

24.驗證一年的12個月:“^(0?[1-9]|1[0-2])$“正确格式為:“01“~“09“和“1“~“12“。

25.驗證一個月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$“正确格式為;“01“~“09“和“1“~“31“。

26.獲取日期正則表達式:d{4}[年|-|.]d{1-12}[月|-|.]d{1-31}日?

評注:可用來匹配大多數年月日信息。

27.匹配雙字節字符(包括漢字在内):[^x00-xff]

評注:可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)

28.匹配空白行的正則表達式:ns*r

評注:可以用來删除空白行

29.匹配HTML标記的正則表達式:<(S*?)[^>]*>.*?|<.*?/>

評注:網上流傳的版本太糟糕,上面這個也僅僅能匹配部分,對于複雜的嵌套标記依舊無能為力

30.匹配首尾空白字符的正則表達式:^s*|s*$

評注:可以用來删除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式

31.匹配網址URL的正則表達式:[a-zA-z]+://[^s]*

評注:網上流傳的版本功能很有限,上面這個基本可以滿足需求

32.匹配帳号是否合法(字母開頭,允許5-16字節,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

評注:表單驗證時很實用

33.匹配騰訊QQ号:[1-9][0-9]{4,}

評注:騰訊QQ号從10000開始

34.匹配中國郵政編碼:[1-9]d{5}(?!d)

評注:中國郵政編碼為6位數字

35.匹配ip地址:((2[0-4]d|25[0-5]|?dd?).){3}(2[0-4]d|25[0-5]|?dd?)。

評注:提取ip地址時有用

FunctionIsRegu(Regu,s)

'正則表達式校驗

IfRegu=““Then

ExitFunction

Endif

DimRe,Sre

SetRe=NewRegExp

Re.Pattern=Regu

Sre=Re.Test(s)

IfSre=TrueThen

IsRegu=True

Else

IsRegu=False

EndIf

EndFunction

tmp=““

if(IsRegu(“w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*“,tmp))=falsethen

msgbox“E-mail地址不合法!“

FieldCheck#N=false

endif

不同的語言(如PHP和JAVA)、相同語言的不同類庫(如來自Sun的JavaRegularExpression類庫跟ApacheJakarta的正則表達式類庫)間,用法會有所差别,在使用的時候,要注意這些差别。

驗證URL

functionIsValidUrl(str){

varregu=“^(https?://)“

+“?(([0-9a-z_!~*'().&=+$%-]+:)?[0-9a-z_!~*'().&=+$%-]+@)?“

+“(([0-9]{1,3}.){3}[0-9]{1,3}“

+“|“

+“([0-9a-z_!~*'()-]+.)*“

+“([0-9a-z][0-9a-z-]{0,61})?[0-9a-z].“

+“[a-z]{2,6})“

+“(:[0-9]{1,4})?“

+“((/?)|“

+“(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$“;

varre=newRegExp(regu);

if(!re.test(str)){

returnfalse;

}

returntrue;

}

零寬斷言

用于查找在某些内容(但并不包括這些内容)之前或之後的東西,也就是說它們像b,^,$那樣用于指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱為零寬斷言。最好還是拿例子來說明吧:

(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表達式exp。比如bw+(?=ingb),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I'msingingwhileyou'redancing.時,它會匹配sing和danc。

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

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

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

斷言用來聲明一個應該為真的事實。正則表達式中隻有當斷言為真時才會繼續進行匹配。

負向零寬

如果我們隻是想要确保某個字符沒有出現,但并不想去匹配它時怎麼辦?例如,如果我們想查找這樣的單詞--它裡面出現了字母q,但是q後面跟的不是字母u,我們可以嘗試這樣:

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

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

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

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

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

相關啟示

(1)心中時刻保持新穎想法,嘗試用各種新辦法來解決遇到的問題。對于遇到的問題,在用常規的解決思路無法解決或不能很好解決的時候,可以大膽探索嘗試采用新的方法或思路來解決問題,說大點就是創新!沒有新思路估計如今的正則表達式還要等幾百年才能露現人間。

(2)善于學習和借鑒前人的經驗和成果,UNIX鼻祖KenThompson是什麼樣子的人?是被計算機界尊稱為“UNIX之父”的大師級别的人物,大師都在不斷思考從其它學科、其它知識領域的工作成果,來改進自己的工作或程序,事實也證明這樣做取得巨大結果和後來的深遠影響是事先誰也無法預估到的,我們在做一些事情或研究的時間,是否也考慮學習大師的優秀習慣?

(3)學好數學、英語并保持對數學、英語的興趣,數學也是人類幾千年積累的智慧結晶,學習數學知識可以培養和訓練人的思維能力。看這篇文章的朋友,我想很多都是計算機相關專業的朋友,至于數學和英語對于計算機學習和發展的重要性的道理,這裡就不在多說,重在實踐加持之以恒!

(4)養成獨立思考的習慣。上學時候老師經常說人與動物的最大區别是人能思考。拉美洲有句關于“思考”的諺語是,不會思考的人是白癡,不肯思考的人是懶漢,不敢思考的人是奴隸。我想大家和我一樣,既不願做懶漢、奴隸,更不願做白癡。所以相信正則分享網的朋友們一定會選擇做一個“會思、肯思、敢思”的人。

(5)當正則表達式和字符串函數都能解決問題時,一定要使用字符串函數,這樣不容易出錯,最重要的是字符串函數比正則表達式實現性能上要好得多。

相關詞條

相關搜索

其它詞條