正則表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。
正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為"元字符")組成的文字模式。模式描述在搜索文本時要匹配的一個或多個字符串。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。
普通字符包括沒有顯式指定為元字符的所有可打印和不可打印字符。這包括所有大寫和小寫字母、所有數字、所有標點符號和一些其他符號。
非打印字符也可以是正則表達式的組成部分。下表列出了表示非打印字符的轉義序列:
所謂特殊字符,就是一些有特殊含義的字符,如上面說的"*.txt"中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls \*.txt。
許多元字符要求在試圖匹配它們時特別對待。若要匹配這些特殊字符,必須首先使字符"轉義",即,將反斜槓字符 (\) 放在它們前面。下表列出了正則表達式中的特殊字符:
限定符用來指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
正則表達式的限定符有:
由於章節編號在大的輸入文檔中會很可能超過九,所以您需要一種方式來處理兩位或三位章節編號。限定符給您這種能力。下面的正則表達式匹配編號為任何位數的章節標題:
/Chapter [1-9][0-9]*/
請注意,限定符出現在范圍表達式之後。因此,它應用於整個范圍表達式,在本例中,只指定從 0 到 9 的數字(包括 0 和 9)。
這裡不使用 + 限定符,因為在第二個位置或後面的位置不一定需要有一個數字。也不使用?字符,因為它將章節編號限制到只有兩位數。您需要至少匹配 Chapter 和空格字符後面的一個數字。
如果您知道章節編號被限制為只有 99 章,可以使用下面的表達式來至少指定一位但至多兩位數字。
/Chapter [0-9]{1,2}/
上面的表達式的缺點是,大於 99 的章節編號仍只匹配開頭兩位數字。另一個缺點是 Chapter 0 也將匹配。只匹配兩位數字的更好的表達式如下:
/Chapter [1-9][0-9]?/
或
/Chapter [1-9][0-9]{0,1}/
*、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的後面加上一個?就可以實現非貪婪或最小匹配。
例如,您可能搜索 HTML 文檔,以查找括在 H1 標記內的章節標題。該文本在您的文檔中如下:
<H1>Chapter 1 – Introduction to Regular Expressions</H1>
下面的表達式匹配從開始小於符號 (<) 到關閉 H1 標記的大於符號 (>) 之間的所有內容。
/<.*>/
如果您只需要匹配開始 H1 標記,下面的"非貪心"表達式只匹配 <H1>。
/<.*?>/
通過在 *、+ 或 ? 限定符之後放置 ?,該表達式從"貪心"表達式轉換為"非貪心"表達式或者最小匹配。
定位符使您能夠將正則表達式固定到行首或行尾。它們還使您能夠創建這樣的正則表達式,這些正則表達式出現在一個單詞內、在一個單詞的開頭或者一個單詞的結尾。
定位符用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結束,\b描述單詞的前或後邊界,\B表示非單詞邊界。
正則表達式的限定符有:
注意:不能將限定符與定位點一起使用。由於在緊靠換行或者字邊界的前面或後面不能有一個以上位置,因此不允許諸如 ^* 之類的表達式。
若要匹配一行文本開始處的文本,請在正則表達式的開始使用 ^ 字符。不要將 ^ 的這種用法與中括號表達式內的用法混淆。
若要匹配一行文本的結束處的文本,請在正則表達式的結束處使用 $ 字符。
若要在搜索章節標題時使用定位點,下面的正則表達式匹配一個章節標題,該標題只包含兩個尾隨數字,並且出現在行首:
/^Chapter [1-9][0-9]{0,1}/
真正的章節標題不僅出現行的開始處,而且它還是該行中僅有的文本。它即出現在行首又出現在同一行的結尾。下面的表達式能確保指定的匹配只匹配章節而不匹配交叉引用。通過創建只匹配一行文本的開始和結尾的正則表達式,就可做到這一點。
/^Chapter [1-9][0-9]{0,1}$/
匹配字邊界稍有不同,但向正則表達式添加了很重要的能力。字邊界是單詞和空格之間的位置。非字邊界是任何其他位置。下面的表達式匹配單詞 Chapter 的開頭三個字符,因為這三個字符出現字邊界後面:
/\bCha/
\b 字符的位置是非常重要的。如果它位於要匹配的字符串的開始,它在單詞的開始處查找匹配項。如果它位於字符串的結尾,它在單詞的結尾處查找匹配項。例如,下面的表達式匹配單詞 Chapter 中的字符串 ter,因為它出現在字邊界的前面:
/ter\b/
下面的表達式匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt:
/\Bapt/
字符串 apt 出現在單詞 Chapter 中的非字邊界處,但出現在單詞 aptitude 中的字邊界處。對於 \B 非字邊界運算符,位置並不重要,因為匹配不關心究竟是單詞的開頭還是結尾。
用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,後者為負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。
對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩沖區中,所捕獲的每個子匹配都按照在正則表達式模式中從左到右出現的順序存儲。緩沖區編號從 1 開始,最多可存儲 99 個捕獲的子表達式。每個緩沖區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩沖區的一位或兩位十進制數。
可以使用非捕獲元字符 '?:'、'?=' 或 '?!' 來重寫捕獲,忽略對相關匹配的保存。
反向引用的最簡單的、最有用的應用之一,是提供查找文本中兩個相同的相鄰單詞的匹配項的能力。以下面的句子為例:
Is is the cost of of gasoline going up up?
上面的句子很顯然有多個重復的單詞。如果能設計一種方法定位該句子,而不必查找每個單詞的重復出現,那該有多好。下面的正則表達式使用單個子表達式來實現這一點:
/\b([a-z]+) \1\b/gi
捕獲的表達式,正如 [a-z]+ 指定的,包括一個或多個字母。正則表達式的第二部分是對以前捕獲的子匹配項的引用,即,單詞的第二個匹配項正好由括號表達式匹配。\1 指定第一個子匹配項。字邊界元字符確保只檢測整個單詞。否則,諸如"is issued"或"this is"之類的詞組將不能正確地被此表達式識別。
正則表達式後面的全局標記 (g) 指示,將該表達式應用到輸入字符串中能夠查找到的盡可能多的匹配。表達式的結尾處的不區分大小寫 (i) 標記指定不區分大小寫。多行標記指定換行符的兩邊可能出現潛在的匹配。
反向引用還可以將通用資源指示符 (URI) 分解為其組件。假定您想將下面的 URI 分解為協議(ftp、http 等等)、域地址和頁/路徑:
http://www.xxxx.com:80/html/html-tutorial.html
下面的正則表達式提供該功能:
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/
第一個括號子表達式捕獲 Web 地址的協議部分。該子表達式匹配在冒號和兩個正斜槓前面的任何單詞。第二個括號子表達式捕獲地址的域地址部分。子表達式匹配 / 和 : 之外的一個或多個字符。第三個括號子表達式捕獲端口號(如果指定了的話)。該子表達式匹配冒號後面的零個或多個數字。只能重復一次該子表達式。最後,第四個括號子表達式捕獲 Web 地址指定的路徑和/或頁信息。該子表達式能匹配不包括 # 或空格字符的任何字符序列。
將正則表達式應用到上面的 URI,各子匹配項包含下面的內容:
常用正則表達式大全!(例如:匹配中文、電話、html等)
匹配中文字符的正則表達式: [u4e00-u9fa5]
評注:匹配中文還真是個頭疼的事,有了這個表達式就好辦了
匹配雙字節字符(包括漢字在內):[^x00-xff]
評注:可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
匹配空白行的正則表達式:ns*r
評注:可以用來刪除空白行
匹配HTML標記的正則表達式:<(S*?)[^>]*>.*?|<.*? />
評注:網上流傳的版本太糟糕,上面這個也僅僅能匹配部分,對於復雜的嵌套標記依舊無能為力
匹配首尾空白字符的正則表達式:^s*|s*$
評注:可以用來刪除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式
匹配Email地址的正則表達式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
評注:表單驗證時很實用
匹配網址URL的正則表達式:[a-zA-z]+://[^s]*
評注:網上流傳的版本功能很有限,上面這個基本可以滿足需求
匹配帳號是否合法(字母開頭,允許5-16字節,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
評注:表單驗證時很實用
匹配國內電話號碼:d{3}-d{8}|d{4}-d{7}
評注:匹配形式如 0511-4405222 或 021-87888822
匹配騰訊QQ號:[1-9][0-9]{4,}
評注:騰訊QQ號從10000開始
匹配中國郵政編碼:[1-9]d{5}(?!d)
評注:中國郵政編碼為6位數字
匹配身份證:d{15}|d{18}
評注:中國的身份證為15位或18位
匹配ip地址:d+.d+.d+.d+
評注:提取ip地址時有用
匹配特定數字:
^[1-9]d*$ //匹配正整數
^-[1-9]d*$ //匹配負整數
^-?[1-9]d*$ //匹配整數
^[1-9]d*|0$ //匹配非負整數(正整數 + 0)
^-[1-9]d*|0$ //匹配非正整數(負整數 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$ //匹配正浮點數
^-([1-9]d*.d*|0.d*[1-9]d*)$ //匹配負浮點數
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$ //匹配浮點數
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$ //匹配非負浮點數(正浮點數 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$ //匹配非正浮點數(負浮點數 + 0)
評注:處理大量數據時有用,具體應用時注意修正
匹配特定字符串:
^[A-Za-z]+$ //匹配由26個英文字母組成的字符串
^[A-Z]+$ //匹配由26個英文字母的大寫組成的字符串
^[a-z]+$ //匹配由26個英文字母的小寫組成的字符串
^[A-Za-z0-9]+$ //匹配由數字和26個英文字母組成的字符串
^w+$ //匹配由數字、26個英文字母或者下劃線組成的字符串
在使用RegularExpressionValidator驗證控件時的驗證功能及其驗證表達式介紹如下:
只能輸入數字:“^[0-9]*$”
只能輸入n位的數字:“^d{n}$”
只能輸入至少n位數字:“^d{n,}$”
只能輸入m-n位的數字:“^d{m,n}$”
只能輸入零和非零開頭的數字:“^(0|[1-9][0-9]*)$”
只能輸入有兩位小數的正實數:“^[0-9]+(.[0-9]{2})?$”
只能輸入有1-3位小數的正實數:“^[0-9]+(.[0-9]{1,3})?$”
只能輸入非零的正整數:“^+?[1-9][0-9]*$”
只能輸入非零的負整數:“^-[1-9][0-9]*$”
只能輸入長度為3的字符:“^.{3}$”
只能輸入由26個英文字母組成的字符串:“^[A-Za-z]+$”
只能輸入由26個大寫英文字母組成的字符串:“^[A-Z]+$”
只能輸入由26個小寫英文字母組成的字符串:“^[a-z]+$”
只能輸入由數字和26個英文字母組成的字符串:“^[A-Za-z0-9]+$”
只能輸入由數字、26個英文字母或者下劃線組成的字符串:“^w+$”
驗證用戶密碼:“^[a-zA-Z]w{5,17}$”正確格式為:以字母開頭,長度在6-18之間,
只能包含字符、數字和下劃線。
驗證是否含有^%&'',;=?$"等字符:“[^%&'',;=?$x22]+”
只能輸入漢字:“^[u4e00-u9fa5],{0,}$”
驗證Email地址:“^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$”
驗證InternetURL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$”
驗證電話號碼:“^((d{3,4})|d{3,4}-)?d{7,8}$”
正確格式為:“XXXX-XXXXXXX”,“XXXX-XXXXXXXX”,“XXX-XXXXXXX”,
“XXX-XXXXXXXX”,“XXXXXXX”,“XXXXXXXX”。
驗證身份證號(15位或18位數字):“^d{15}|d{}18$”
驗證一年的12個月:“^(0?[1-9]|1[0-2])$”正確格式為:“01”-“09”和“1”“12”
驗證一個月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$”
正確格式為:“01”“09”和“1”“31”。
匹配中文字符的正則表達式: [u4e00-u9fa5]
匹配雙字節字符(包括漢字在內):[^x00-xff]
匹配空行的正則表達式:n[s| ]*r
匹配HTML標記的正則表達式:/<(.*)>.*|<(.*) />/
匹配首尾空格的正則表達式:(^s*)|(s*$)
匹配Email地址的正則表達式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配網址URL的正則表達式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?
(1)應用:計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}
(2)應用:JavaScript中沒有像vbscript那樣的trim函數,我們就可以利用這個表達式來實現
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
(3)應用:利用正則表達式分解和轉換IP地址
function IP2V(ip) //IP地址轉換成對應數值
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正則表達式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
(4)應用:從URL地址中提取文件名的javascript程序
s="http://www.xxxx.com/page1.htm";
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2") ;//Page1.htm
(5)應用:利用正則表達式限制網頁表單裡的文本框輸入內容
用正則表達式限制只能輸入中文:onkeyup="value=value.replace(/[^u4E00-u9FA5]/g,'')
"onbeforepaste="clipboardData.setData(''text'',clipboardData.getData(''text'').replace(/[^u4E00-u9FA5]/g,''))"
用正則表達式限制只能輸入全角字符: onkeyup="value=value.replace(/[^uFF00-uFFFF]/g,'')
"onbeforepaste="clipboardData.setData(''text'',clipboardData.getData(''text'').replace(/[^uFF00-uFFFF]/g,''))"
用正則表達式限制只能輸入數字:onkeyup="value=value.replace(/[^d]/g,'')
"onbeforepaste=
"clipboardData.setData(''text'',clipboardData.getData(''text'').replace(/[^d]/g,''))"
用正則表達式限制只能輸入數字和英文:onkeyup="value=value.replace(/[W]/g,'')
"onbeforepaste="clipboardData.setData(''text'',clipboardData.getData(''text'').replace(/[^d]/g,''