正則表達式,英文 Regular expression,簡(jiǎn)寫(xiě)Regexes或Regex。
應用概述:提供與預期的搜索結果匹配的確切文本來(lái)進(jìn)行字符串的搜索和替換操作。這種技術(shù)不僅僅用于開(kāi)發(fā)領(lǐng)域,更被集成到一些常見(jiàn)的文本擴展編輯器,如UltraEdit、EmEditor等。歷史上第一個(gè)實(shí)用應用程序是Unix 中的Qed 編輯器。
舉一個(gè)簡(jiǎn)單的類(lèi)比:我們對DOS中的通配符"*"和"?"應該很熟悉,如命令"dir *.exe" 將列出所有后綴名為exe的文件名。正則表達式提供的方法與其類(lèi)似,而且遠比通配符強大的多。
從某種意義上說(shuō),正則表達式是一種語(yǔ)言,通過(guò)及其簡(jiǎn)短的一行代碼即可以高效、精確的描述要匹配的復雜文本,當然,它最大的優(yōu)點(diǎn)也是他最大的缺點(diǎn):語(yǔ)法復雜,創(chuàng )建困難。
主要應用:
數據驗證 這是正則表達式在開(kāi)發(fā)中最常見(jiàn)的應用,通過(guò)測試字符串內的模式。來(lái)驗證輸入的字符串是否為郵政編碼、電話(huà)號碼、電子郵件地址、信用卡號碼等等。
搜索和替換文本 用正則表達式來(lái)搜索文檔中的特定文本塊,根據需要用其他指定的文本塊進(jìn)行替換。這也是文本編輯中的一個(gè)常見(jiàn)應用,如將網(wǎng)頁(yè)中的HTML代碼轉化為UBB代碼。
既然發(fā)在“軟件使用”板,正則表達式的開(kāi)發(fā)應用就不介紹了,以下僅以EmEditor中的正則表達式來(lái)作介紹:
1.啟用正則表達式
菜單:搜索-查找,選中“使用正則表達式”。
2. Emeditor 正則語(yǔ)法
正則表達式是普通字符和元字符組合的一種模式。它的結構與算術(shù)表達式的結構類(lèi)似,各種元字符和運算符可以將小的表達式組合起來(lái),創(chuàng )建大的表達式。通過(guò)在一對分隔符之間放置表達式模式的各種組件,就可以構建正則表達式。
2.1 普通字符
普通字符是指除了 " . "、 "*"、"?"、 "+"、 "("、 ")"、 "{"、 "}"、 "["、 "]"、"^"、 "$" 和 "\" 這些特殊字符之外的所有其他字符。而這些特殊字符也可以通過(guò)前面加上"\"前綴而變?yōu)槠胀ㄗ址?。比如,搜?CCF"即為在文本中匹配所有的"CCF"字符串,搜索"\[CCF\]"則是在文本中匹配所有的"[CCF]"字符串。
簡(jiǎn)而言之,普通字符即為只匹配自身的字符。
2.2 元字符
元字符不匹配其自身,它用特殊方式來(lái)解析從而實(shí)現更多的邏輯功能。正則表達式通過(guò)元字符在模式中包含選擇和循環(huán)
2.2.1 特殊字符
. 匹配除換行符 \n 之外的任何單個(gè)字符。
( ) 分組捕獲(子表達式)的開(kāi)始和結束??梢圆东@子表達式以供以后使用。
[ ] 中括號表達式的開(kāi)始。
中括號表達式是在方括號內包含一個(gè)或多個(gè)字符構成的列表的表達式。普通字符在中括號內表示本身,大多數特殊字符在中括號表達式內出現時(shí)失去它們的意義。除了轉義字符'\',(要包含'\',需要使用'\\') 如:正則表達式 No [1234] 匹配 No 1,No 2,No 3 和 No 4。
如果想在中括號中使用一個(gè)范圍作為列表來(lái)匹配字符,可以用連字符 '-' 將范圍中的開(kāi)始字符和結束字符分開(kāi)。單個(gè)字符的字符值確定范圍內的相對順序。如:正則表達式 No [1-4] = No [1234]
注意
?、匍_(kāi)始值的Unicode值必須在結束值Unicode值的前面。
?、赱\-]匹配連字符'-',放在中括號列表的開(kāi)始或結尾也可起到同樣的效果,如 [-c-f] 匹配 c 至 f 的字符和連字符
如果需要匹配不屬于列表或范圍內的任何字符,可以在列表開(kāi)頭加上'^'前綴。如:正則表達式 No [^1-4] 匹配 No 5 和更大的編號。
中括號表達式還可進(jìn)行組合,如 [A-Za-z0-9] 匹配A-Z,a-z,0-9 的字符
\ 將下一字符標記為特殊字符、文本、反向引用或八進(jìn)制轉義符。例如:
?、僮址?n 匹配字符 n
?、赲n 匹配換行符
?、坌蛄?\\ 匹配 \
?、苄蛄?\( 匹配 (
| 替換字符,對 | 左右的兩個(gè)項分別匹配進(jìn)行選擇?;蛘哒f(shuō),就是邏輯的OR的概念。
{ } 標記限定符表達式的開(kāi)始。
(數量)限定字符
限定字符能夠指定正則表達式的某個(gè)部分必須出現的次數
* 零次或多次匹配前面的字符或子表達式。如,c*f 可以匹配 f 和 ccf。* = {0,}
+ 一次或多次匹配前面的字符或子表達式。如,c+f 可以匹配 cf 和 ccf,但不匹配 f。+ = {1,}
零次或一次匹配前面的字符或子表達式。如,cc?f 可以匹配 cf 或 ccf。? = {0,1}
{n} n 是非負整數。正好匹配 n 次。如,c{2}f 可以匹配 ccf。
{n,} n 是非負整數。至少匹配 n 次。如,c{2,}f 不匹配 cf,而可以匹配 ccccccf。c{1,} = c+,c{0,} = c*。
{n,m} m 和 n 是非負整數,其中 n <= m。至少匹配 n 次,至多匹配 m 次。如,c{1,3} 可以匹配 ccf 中的cc。c{0,1} = c?。
2.2.2 控制字符
\a Bell 字符。= 0x07
\f 換頁(yè)符匹配。= 0x0C
\n 換行符匹配。= 0x0A
\r 匹配一個(gè)回車(chē)符。= 0x0D
\t 制表符匹配。= 0x09
\v 垂直制表符匹配。= 0x0B
\e ASCII 換碼字符。= 0x1B
\0dd 八進(jìn)制換碼字符,dd代表八進(jìn)制數字。
\xXXXX或\x{XXXX} 4位十六進(jìn)制Unicode字符,XXXX代表十六進(jìn)制數字。
\cZ Z-'@' 控制字符Control-Z,Z為大于等于"@"的ASCII字符
2.2.3 換碼字符
\w 任一單詞字符,如A-Z,a-z,0-9,_等,如 \w\w\w可以匹配 U_4 但不匹配 %^e
\W 任一非單詞字符,如 \W\W 可以匹配 *& 但不匹配 7#
\s 任一空白字符,包括空格、制表符、換頁(yè)符、回車(chē)符和垂直制表符。= [ \f\n\r\t\v]
\S 任一非空白字符。= [^ \f\n\r\t\v]
\d 0-9的任一數字字符,如 \d\d可以匹配 54 但不匹配 a4
\D 任一非數字字符。如 \D\D可以匹配 a4 但不匹配 54
\l a-z 之間的任一小寫(xiě)字符,如 \l\l\l可以匹配 ccf 但不匹配 ccF
\L 任一非小寫(xiě)字符,如 \L\L\L可以匹配 CCF 但不匹配 cCF
\u a-z 之間的任一大寫(xiě)字符,如 \u\u\u可以匹配 CCF 但不匹配 CCf
\U 任一非大寫(xiě)字符,如 \U\U\U可以匹配 ccf 但不匹配 ccF
\C 任一字符,\C =.
\Q 前置引號符,其后的任意字符均被認為普通字符直至出現后置引號符\E。同時(shí)匹配單引號和雙引號
\E 后置引號符
2.2.4 轉義字符串
表示為[:classname:],如"[[:space:]]"表示所有的空格字符
alnum 任一單詞字符和數字字符。= [\w\d]
alpha 任何一個(gè)單詞字符,如A-Z,a-z,0-9
blank 任一空白字符,包括空格、制表符、換頁(yè)符、回車(chē)符和垂直制表符。= [ \f\n\r\t\v] = \s
cntrl 任一控制字符。
digit 0-9的任一數字字符,= \d
graph 任一圖形字符。
lower a-z 之間的任一小寫(xiě)字符 =\l
print 任一可打印字符 = '.' = \C
punct 任一標點(diǎn)符號
space 任一空格字符
upper a-z 之間的任一大寫(xiě)字符 = \u
xdigit 4位十六進(jìn)制Unicode字符,= \xXXXX
word 任何一個(gè)單詞字符,如A-Z,a-z,0-9,_等,= \w
unicode 任何一個(gè)ASCII值大于255的字符
2.2.5 定位字符
定位字符可以把正則表達式固定到行首或行尾。在Perl正則全集中還能使正則表達式出現在一個(gè)單詞內、在一個(gè)單詞的開(kāi)頭或者一個(gè)單詞的結尾,EmEditor只是一個(gè)子集,不包含這個(gè)功能。
^ 匹配輸入字符串開(kāi)始的位置。如果設置customize中的"regular expressions can match new line characters",那么 ^ 還匹配 \n 或 \r 后面的位置。 但在中括號表達式中使用的情況除外,在那種情況下它對字符集求反。
$ 匹配輸入字符串結尾的位置。如果設置customize中的"regular expressions can match new line characters",那么 $ 還匹配 \n 或 \r 前面的位置。
3.分組捕獲和替換
分組通常用來(lái)捕獲特定模式的一組文本,并用與之后的替換操作,這也就是將分組和替換結合起來(lái)講解的原因。
最基本的分組構造方式就是(),在左右括號中括起來(lái)的部分,就是一個(gè)分組;在正則全集中還有如(? )的命名分組方式,這種方式組合了模式在就是對分組的部分進(jìn)行了命名,這樣就可以通過(guò)該組的命名來(lái)獲取信息,但這種方式在EmEditor中不被支持。以下分別來(lái)介紹各種不同的分組:
() 組捕獲。這種分組對模式在括號內所捕獲的字符進(jìn)行組合,并且每個(gè)分組捕獲的匹配結果都將保存為一個(gè)實(shí)體以備其后的操作所引用。甚至在正則全集中還可對前面的分組進(jìn)行反向引用(這是題外話(huà),EmEditor不支持)。舉例說(shuō)明:
源文本:
代碼:
site status- online members:65,online guests:12
使用正則表達式:
代碼:
(members|guests):其后是冒號和一個(gè)空格,最后匹配至少一個(gè)數字。匹配模式結果如下:
代碼:
members:65
guests:12
其中members和guests在兩次匹配中被捕捉,可以在隨后的操作中引用。
(?:) 非組捕獲. 這種分組僅僅對模式在括號內所匹配的字符進(jìn)行組合,模式所匹配的字符將不會(huì )作為一個(gè)組來(lái)捕獲. 雖然他也同樣成為最終的匹配結果的一部分,但無(wú)法為其后的操作所引用. 同樣以上例繼續:
使用正則表達式:
代碼:
(?:members|guests):\d+
匹配模式結果同樣為:
代碼:
members:65
guests:12
但是members和guests僅僅在兩次匹配中被分組,并不被捕獲,也不可以在隨后的操作中引用。
使用非捕獲組有其原因和場(chǎng)合. 其一,從效率上說(shuō),捕獲一個(gè)分組需要消耗額外的資源和處理時(shí)間,所以不應該捕獲不需要使用的數據. 其二,對模式中有多個(gè)捕獲組的情況,對不需要處理的分組進(jìn)行捕獲只會(huì )對分組信息造成混亂. 其三,避免不需要貪婪匹配的場(chǎng)合發(fā)生貪婪匹配,貪婪匹配是正則引擎的一個(gè)重要特性,要說(shuō)清楚其機理可能還需要另外開(kāi)一個(gè)專(zhuān)題了,對這一點(diǎn),還以上例說(shuō)明一下:
使用不帶分組的正則表達式:
代碼:
members|guests:\d+
匹配模式為:
代碼:
members
guests:12
這個(gè)正則表達式的問(wèn)題在于,他匹配的是"members" 或 "guests:\d+",這是模式中貪婪"消費"字符引起的。 而通過(guò)增加括號進(jìn)行分組,使正則引擎將兩個(gè)匹配選項作為一個(gè)組處理,從而正確匹配其中的一個(gè)匹配項。
(?=) 正聲明組,非捕獲. 此分組中的模式必須出現在聲明的右側,并且,這個(gè)模式不構成匹配結果的一部分. 舉例:
源文本:
代碼:
site status- online members:65,online guests:12
使用正則表達式:
代碼:
\S+(?=\s\d+)
此模式中規定了\s\d+必須出現在\S+聲明的右側. 也就是說(shuō),在至少一個(gè)非空格字符(聲明)的右側必須出現一個(gè)空格字符和至少一個(gè)數字,而且只有這個(gè)聲明構成匹配結果. 匹配模式結果如下:
代碼:
members:
guests:
這兩次匹配中不被捕捉。
(?!) 負聲明組,非捕獲. 此分組中的模式不得出現在聲明的右側,并且,這個(gè)模式不構成匹配結果的一部分. 還是用上面的例子:
使用正則表達式:
代碼:
\d{2}(?!,)
此模式中規定了","不得出現在\d{2}聲明的右側. 也就是說(shuō),在連續兩個(gè)數字(聲明)的右側不得出現逗號才能被匹配. 匹配模式結果如下:
代碼:
12
這兩次匹配中不被捕捉。
嚴格的說(shuō),后面兩個(gè)分組不能稱(chēng)之為分組,他們只是模式聲明,他們不能成為匹配結果,也不能被捕獲. 在正則全集中,還有反向聲明分組(?<=)(?),在EmEditor中不被支持。
說(shuō)到括號的功能,本來(lái)正則中的一個(gè)重要指令-條件指令和分組內聯(lián)設定是不得不說(shuō)的,可惜的是... EmEditor也同樣不支持~~~~
在前面的例子中一直提到匹配之后的操作,而這個(gè)進(jìn)一步的操作最常見(jiàn)的就是替換. 先繼續上面的例子:
源文本:
代碼:
site status- online members:65,online guests:12
使用搜索正則表達式:
代碼:
(members|guests)
和替換正則表達式:
代碼:
ccf-\1
匹配模式結果如下:
代碼:
members
guests
替換后的文本為:
代碼:
site status- online ccf-members:65,online ccf-guests:12
其中members和guests在兩次匹配中被捕捉,在隨后被引用,并添加ccf-前綴后替換源文本中的匹配字符。
在匹配模式中的分組匹配結果將按前后順序被正則引擎分別賦予內部組號,在替換操作中就可以用\加上這個(gè)組號來(lái)引用相應的匹配結果. 繼續上例:
使用搜索正則表達式:
代碼:
(members|guests):(\d{2})
和替換正則表達式:
代碼:
ccf-\1 = \2
匹配模式結果如下:
代碼:
members:65
guests:12
替換后的文本為:
代碼:
site status- online ccf-members = 65,online ccf-guests = 12
在EmEditor的正則子集中增加了一個(gè)特殊的引用:\0 ,\0 將引用上次的匹配結果,繼續把:
使用搜索正則表達式:
代碼:
\d{2}
和替換正則表達式:
代碼:
*\0*
匹配模式結果如下:
代碼:
65
12
替換后的文本為:
代碼:
site status- online ccf-members:*65*,online ccf-guests:*12*
作為一個(gè)編輯軟件,EmEditor的正則子集中增加了一些替換修飾符:
\U 大寫(xiě)修飾. 將其后的所有的字符替換為大寫(xiě)
\L 小寫(xiě)修飾. 將其后的所有的字符替換為小寫(xiě)
\H 半角修飾. 將其后的所有的字符替換為半角字符. 寫(xiě)到這里,不得不稱(chēng)許一下EmEditor對中文的良好支持,這個(gè)\H至少我是很常用的,不喜歡看到文本里面都是些123abc之類(lèi)的全角字符..。
\F 全角修飾. 將其后的所有的字符替換為全角字符
\E 關(guān)閉之前的\U,\L,\H,\F修飾。
4.高級運用
?。?)^[ \t]*\n
這個(gè)正則表達式代表所有的空行,指含有零個(gè)或零個(gè)以上空格或制表符、以換行符結尾、不含其它字符的行。
(2)(^|(?<=中國)).*?(?=中國|$)
用正則表達式匹配特定字符串外的所有字符。指除“中國”外的所有其它字符,類(lèi)似于反選功能。
?。?)^[ \t]+
查找以上字符,并替換為空,可刪除行首空白(包括全半角空格和制表符)。
(4)[ \t]+$
查找以上字符,并替換為空,可刪除行末空白(包括全半角空格和制表符)。
?。?)^[ \t]+|[ \t]+$
查找以上正則表達式,并替換為空,可刪除行首和行末所有空白(包括全半角空格和制表符)。9FA5
?。?)[\u4E00-\u9FA5]或[一-龥](méi)
匹配中文字符。評注:匹配中文還真是個(gè)頭疼的事,有了這個(gè)表達式就好辦了
?。?)[^\x00-\xff]
匹配雙字節字符(包括漢字在內)。評注:可以用來(lái)計算字符串的長(cháng)度(一個(gè)雙字節字符長(cháng)度計2,ASCII字符計1)
?。?)\n\s*\r
匹配空白行的正則表達式。評注:可以用來(lái)刪除空白行,我覺(jué)得\n[\s\t]*$更好)。
?。?)< (\S*?)[^>]*>.*?|< .*? />
匹配HTML標記的正則表達式。評注:網(wǎng)上流傳的版本太糟糕,上面這個(gè)也僅僅能匹配部分,對于復雜的嵌套標記依舊無(wú)能為力
?。?0)^\s*|\s*$
匹配首尾空白字符的正則表達式。評注:可以用來(lái)刪除行首行尾的空白字符(包括空格、制表符、換頁(yè)符等等),非常有用的表達式
?。?1)\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配Email地址的正則表達式。評注:表單驗證時(shí)很實(shí)用。
?。?2)[a-zA-z]+://[^\s]*
匹配網(wǎng)址url的正則表達式。評注:網(wǎng)上流傳的版本功能很有限,上面這個(gè)基本可以滿(mǎn)足需求。
?。?3)^[a-zA-Z][a-zA-Z0-9_]{4,15}$
匹配賬號是否合法(字母開(kāi)頭,允許5-16字節,允許字母數字下劃線(xiàn))。評注:表單驗證時(shí)很實(shí)用。
?。?4)\d{3}-\d{8}|\d{4}-\d{7}
匹配國內電話(huà)號碼。評注:匹配形式如 0511-4405222 或 021-87888822
?。?5)[1-9][0-9]{4,}
匹配騰訊QQ號。評注:騰訊QQ號從10000開(kāi)始
?。?6)[1-9]\d{5}(?!\d)
匹配中國郵政編碼。評注:中國郵政編碼為6位數字
?。?7)\d{15}|\d{18}
匹配身份證。評注:中國的身份證為15位或18位
?。?8)\d+\.\d+\.\d+\.\d+
匹配IP地址。評注:提取IP地址時(shí)有用。
?。?9)匹配特定數字:
^[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*$ //匹配正浮點(diǎn)數
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ //匹配負浮點(diǎn)數
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ //匹配浮點(diǎn)數
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ //匹配非負浮點(diǎn)數(正浮點(diǎn)數 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ //匹配非正浮點(diǎn)數(負浮點(diǎn)數 + 0)
評注:處理大量數據時(shí)有用,具體應用時(shí)注意修正
?。?0)匹配特定字符串
^[A-Za-z]+$ //匹配由26個(gè)英文字母組成的字符串
^[A-Z]+$ //匹配由26個(gè)英文字母的大寫(xiě)組成的字符串
^[a-z]+$ //匹配由26個(gè)英文字母的小寫(xiě)組成的字符串
^[A-Za-z0-9]+$ //匹配由數字和26個(gè)英文字母組成的字符串
^\w+$ //匹配由數字、26個(gè)英文字母或者下劃線(xiàn)組成的字符串
^.*John.*$ //匹配包括“John”的整行。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。