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