1.正則表達式簡介
正則表達式(Regular expression,簡寫爲Regexes)是一種用來操作和檢驗字符串數據的強大工具。它相當與一串特殊的字符,用它可以轉換成算法,對文本進行匹配等操作。
事實上正則表達式有其自身的一套語法,這種語法對於初學者來說顯得有些晦澀難懂。尤其是其構造比較困難,稱爲很多入門者的障礙。但當掌握後卻可以輕易的解決以前不容易解決的很多文本類問題,如驗證提取等。
其常用場合有如下三種:
Ø測試字符串的某個模式。例如,可以對一個輸入字符串進行測試,看在該字符串是否存在一個電話號碼模式或一個信用卡號碼模式。這稱爲數據有效性驗證。
Ø替換文本。可以在文檔中使用一個正則表達式來標識特定文字,然後可以全部將其刪除,或者替換爲別的文字。
Ø根據模式匹配從字符串中提取一個子字符串。可以用來在文本或輸入字段中查找特定文字。
2.正則表達式基礎語法
2.1匹配不同類型的字符
字符類 |
匹配的字符 |
\d | 匹配一個數字字符。等價於 [0-9]。 |
\D | 匹配一個非數字字符。等價於 [^0-9]。 |
\w | 匹配包括下劃線的任何單詞字符。等價於‘[A-Za-z0-9_]‘。 |
\W | 匹配任何非單詞字符。等價於 ‘[^A-Za-z0-9_]‘。 |
\s | 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。 |
.(點號) | 任一字符 |
[…] | 括號中的任一字符 |
[^…] | 非括號中的任一字符 |
2.2定位控制字符
^ | 其後的模式必須在字符串的開始處,如果是多行則在任一行的開始C#需要設定Multiline標誌 |
$ | 前面的模式必須在一行的末尾,如果是多行,則在任意行的末尾 |
\A | 前面的模式必須在字符串的開始處;多行標誌被忽略 |
\z | 前面的模式必須在字符串的末尾處,多行標誌被忽略 |
\Z | 前面的模式必須位於字符串的末尾或位於換行符前 |
\b | 匹配一個單詞字符的開始,單詞字符是[a-zA-Z0-9]中的一位 |
\B | 匹配一個非單詞邊界的位置, 不在一個單詞的開始 |
2.3指定重複字符
{n} | 匹配前面的字符n次 |
{n,} | 匹配前面的字符最少n次 |
{n,m} | 匹配前面的字符n至m次 |
? | 匹配前面的字符0次或1次 |
+ | 匹配前面的字符至少1次 |
* | 匹配前面的字符至少0次 |
2.4特殊控制類
| | 指定字符替換,即該位置可以是|兩邊的任一個表達式 |
2.5 特殊字符轉義序列
\\ | 匹配“\” |
\. | 匹配”.“ |
\* | 匹配”*“ |
\( | 匹配”(” |
\) | 匹配“)” |
\? | 匹配”?” |
\+ | 匹配”+“ |
\| | 匹配”|“ |
\{ | 匹配”{“ |
\} | 匹配”}“ |
\^ | 匹配”^“ |
\$ | 匹配”$“ |
\n | 匹配換行符 |
\r | 匹配回車 |
\t | 匹配Tab鍵 |
\v | 匹配垂直製表符 |
\f | 匹配換頁符 |
\nnn | 匹配一個三位八進制數指定的ASCII字符,如\103匹配C |
\xnn | 匹配一個二位16進制數指定的ASCII字符,例如\x43匹配C |
\unnnn | 匹配一個4位16進制數指定的Unicode字符 |
\cV | 匹配一個控制字符,(如複製Ctrl+C) |
2.6正則表達式分組、替換、反向引用等高級應用
以上只是正則表達式的基礎部分,從這裏開始纔算真正開始正則表達式之旅。
²分組
分組技術可以匹配在一個組中的所有字符,用()來表示,是下面兩個技術的基礎所在。”()”又稱捕獲符號。
1.捕獲:()
例子:ABC1EDF2UU
匹配組表達式:([A-Z]{3})\d–匹配3個連續大寫字母和一個數字
匹配結果:1.ABC1,2.EDF2
如果用C#中的group,則爲ABC,EDF。因爲group蒐集的是匹配組的內容。
2.非捕獲(?:)
使用了非捕獲就說明該()中的內容將不作爲捕獲的組返回,而和其它表達式共同構成匹配項返回。也就是捕獲組將不存在。
例:1AF3EDC
匹配表達式:(?:\d|[A-Z])\w–匹配一個數字或字母加一個任意的字符。
匹配結果:1.1A 2.F3 3.ED
沒有組被捕獲
2.通過名稱捕獲(?<name>)
定義了名稱捕獲的組可以在反向匹配中運用名稱進行反向引用而不需要再使用數字進行反向捕獲。注意組名區分大小寫!
²替換
替換,顧名思義,是將匹配的字符替換成其他指定的字符形式。這個功能是在分組的基礎上的(當然或許可以單獨存在,但是那樣匹配的功能顯然不夠強大)。在這裏有一個技巧是使用附加的匹配字符控制匹配內容。
$group | 用group指定的組號進行替換 |
${name} | 替換由<?name>匹配的最後一個子串 |
$$ | 替換字符$ |
$& | 替換整個的匹配 |
$+ | 替換最後捕獲的組 |
$ | 替換整個輸入的字符串 |
²反向引用
反向匹配可以引用前面組中的匹配形式。”\匹配組的數字表示(1爲基數)”或者”\k<groupname>“
²高級組
1.正聲明(?=)
規定了括號中的模式必須出現在聲明的右側。模式將不構成匹配的一部分。
2.負聲明(?!)
規定了括號中的模式不能出現在聲明的右側,模式將不構成匹配的一部分。
3.反向正聲明(?<=)
規定了括號中的模式必須出現在聲明的左側,模式將不構成匹配的一部分。
4.反向負聲明(?<!)
規定了括號中的模式必須出現在聲明的左側。模式不構成匹配的一部分。
5.非回溯(?>)
防止了正則表達式引擎搜索失敗時回溯,這稱之爲貪婪的子表達式。
如輸入字符串:Hewas very trusting.
正則表達式:.*ing將匹配trusting但是如果加入(?>)ing則不能完成匹配。
非回溯組也是非捕獲組。他對於提高正則表達式的效率很有效。
如匹配一個www.****.com的網址。使用www\.(.*)\.com顯然要比www\.([^.]*)\.com效率要低的多,因爲前者必須使用組中的回溯操作,回溯是很艱難的過程,所以當使用非回溯的正則表達式時時可以顯著提高正則表達式的效率的。
其實正則表達式是隻注重匹配結果的,所以會努力去匹配所存在的字符串。這就是它的貪婪性所在。(這點其實理解的不是太深)。
注意以上這些(1-5)都不能夠用於反向引用,因爲以上聲明將不作爲匹配的一部分。
2.7在正則表達式中做決策
高級決策的兩種寫法:
1=>(?(expression)yes|no)
2=>(?(?=expression)yes|no)
這兩種方式中的的expression匹配則後面進行匹配yes,否則匹配no。
需要注意的一點是yes測試和決策測試是在同一個起點裏進行的。
如以下字符串:77-77A 69-AA 57-B
匹配表達式爲:(\d7)?-(?(1)\d\d[A-Z]|[A-Z][A-Z])
匹配結果爲:
1.77-77A2. –AA
這個正則表達式中用到了引用組,(?(1)**)中的1也可以換爲\1,這樣不影響匹配。這個匹配中如果將決策後面的\d\d去掉則會出現不同的結果,這時只會有一個-AA是匹配的。因爲決策點和yes表達式是從同一個起點開始匹配所以即使決策點匹配了,但是後面的yes表達式仍然不匹配。就只匹配no部分的表達式。最終結果也必然改變,理解這一點很重要。
2.8 正則表達式的選項
快到結尾了,再說下正則表達式的選項。選項其實就是將正則表達式的設置改到組中來。如(?i:[a-z])將忽略大小寫進行匹配。實際上如果學過Javascript中的正則表達式,可以看出這個i在javascript中表示的還是這個意思。
N | 規定只有顯示命名的組標號的組纔能有效的捕獲 |
I | 此選項匹配不區分大小寫的匹配 |
X | 此選項規定,非轉義的空字符被排除在模式之外,並啓用了一個前綴#的註釋 |
M | 指定多行模式,修改了^和$的定義 |
S | 指定單行模式 |
2.9正則表達式的規則
1.正則表達式會對輸入字符傳進行最快的匹配,它一次搜索一個字符,知道實現第一次匹配。
2.發現一個匹配的開始後,正則表達式引擎將繼續匹配,直到遇到一個不被模式接收的字符。
3.Regex引擎非常貪婪—只要模式匹配它將匹配儘可能多的字符。
4.Regex渴望實現匹配,所以將在需要時回溯以實現匹配。
5.Regex引擎總是先選擇第一個選項。在|式表達式中。
以上的幾點很重要。到這正則表達式的幾乎所有規則也就講完了。
最後附一個懶惰匹配常用修飾和其他的限定
*? | 儘可能少地使用重複的第一個匹配 |
+? | 儘可能少地使用重複但至少使用一次 |
?? | 使用零次重複(如有可能)或一次重複 |
{n}? | 等同於{n} |
{n, }? | 儘可能少地使用重複但至少使用n次 |
{n,m}? | 介於n和m之間,儘可能少地使用重複 |
常用正則驗證規則40條
decmal:”^([+-]?)\\d*\\.\\d+$”, //浮點數
decmal1:”^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$”, //正浮點數
decmal2:”^-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*)$”, //負浮點數
decmal3:”^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$”, //浮點數
decmal4:”^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0$”, //非負浮點數(正浮點數 + 0)
decmal5:”^(-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*))|0?.0+|0$”, //非正浮點數(負浮點數 + 0)
intege:”^-?[1-9]\\d*$”, //整數
intege1:”^[1-9]\\d*$”, //正整數
intege2:”^-[1-9]\\d*$”, //負整數
num:”^([+-]?)\\d*\\.?\\d+$”, //數字
num1:”^[1-9]\\d*|0$”, //正數(正整數 + 0)
num2:”^-[1-9]\\d*|0$”, //負數(負整數 + 0)
ascii:”^[\\x00-\\xFF]+$”, //僅ACSII字符
chinese:”^[\\u4e00-\\u9fa5]+$”, //僅中文
color:”^[a-fA-F0-9]{6}$”, //顏色
date:”^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$”, //日期
email:”^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$”, //郵件
idcard:”^[1-9]([0-9]{14}|[0-9]{17})$”, //身份證
ip4:”^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$”, //ip地址
letter:”^[A-Za-z]+$”, //字母
letter_l:”^[a-z]+$”, //小寫字母
letter_u:”^[A-Z]+$”, //大寫字母
mobile:”^0?(13|15|18)[0-9]{9}$”, //手機
mobile2:”^(1[3458])[0-9]{9}|((\+852|00852)[9|8|6|5])[0-9]{7}$” //支持香港手機號
tel1:”^(0[0-9]{2,3}\\-)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?$” //固定電話
tel2:”^((0[0-9]{2,3}\-)?[2-9][0-9]{6,7}|((00852|\+852)\-)?([2-3][0-9]{7}))+(\-[0-9]{1,4})?$” //固定電話(支持香港固話)
notempty:”^\\S+$”, //非空
password:”^.*[A-Za-z0-9\\w_-]+.*$”, //密碼
fullNumber:”^[0-9]+$”, //數字
picture:”(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$”, //圖片
qq:”^[1-9]*[1-9][0-9]*$”, //QQ號碼
rar:”(.*)\\.(rar|zip|7zip|tgz)$”, //壓縮文件
tel:”^[0-9\-()()]{7,18}$”, //電話號碼的函數(包括驗證國內區號,國際區號,分機號)
url:”^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$”, //url
username:”^[A-Za-z0-9_\\-\\u4e00-\\u9fa5]+$”, //用戶名
deptname:”^[A-Za-z0-9_()()\\-\\u4e00-\\u9fa5]+$”, //單位名
zipcode:”^\\d{6}$”, //郵編
realname:”^[A-Za-z\\u4e00-\\u9fa5]+$”, // 真實姓名
companyname:”^[A-Za-z0-9_()()\\-\\u4e00-\\u9fa5]+$”,
companyaddr:”^[A-Za-z0-9_()()\\#\\-\\u4e00-\\u9fa5]+$”,
companysite:”^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&#=]*)?$”