正則表達式[]里的五個特殊字符
在正則表達式[]里面,主要的特殊字符有五個:[]-\^。
它們在特定情況下,需要表達本身的字面意思,就需要做轉義處理;如果不做轉義處理,可能會得到其他的意義,從而得到錯誤的匹配結果。
除了這五個字符以外,在[]中的.、*、+、|都是沒有任何特殊意義的,它們都表示它們本身的字面意思,也就是說,*就是*。
下面深入講解下正則表達式[]里的這五個特殊字符:
(一)[ 和 ]
因為與正則表達式[]本身沖突,因此,需要匹配其本身時,需要進行轉義處理。
例如,
源文本:我是一名[PHP]工程師,而不是一名[Java]工程師,也不是一名[C++]工程師,更不是一名[C#]工程師。
需求:匹配[]中的工程師類型,工程師類型由大小寫字母和+#構成。
正則:\[([a-zA-Z+#]+)\]
(二)-
一般情況下,我們會使用[0-9]或者[a-z]這樣的表達式來表達數字和小寫字母,也就是說,-在此處的意思是表達一個范圍值,即從0到9和從a到z。
如果我們想要得到一個由*或-或+組成的匹配時,可能有些人會寫成[*-+],而且,有些時候測試用例不完整的情況下,還發現不了問題。
[*-+]這個表達式其實表示的是*的ASCII值到+的ASCII值的范圍,在我們常見的字母、數字、特殊字符區間里,它剛好能匹配*和+,卻並沒像預期那樣匹配到-。甚至,如果你寫成了[+-*],它還會報錯,就像你不能寫成[9-0]一樣,它會提示你:Warning: preg_match(): Compilation failed: range out of order in character class at offset 3。而如果你寫成了[-*+]或者[*+-],那么恭喜你,你碰巧寫對了。
因此,對於[]中的-,如果需要表達其字面意思,除非我們把它寫到了[]的開頭或者結尾,我們都是需要做轉義處理的,也就是[*\-+]。雖然寫到開頭或結尾不需要轉義,但我還是建議,需要表達-本身字面意思時,最好都使用轉義,這也便於維護者對於該表達式的理解。
(三)\
\本身是轉義符,如果你不對它做轉義,它將對其后面的字符做轉義,所以,這個字符要表達其字面意思時,必須做轉義,也就是\\。
(四)^
^我們常見用法是[^0-9]這種,在[]中放到開頭,用於表示排除,也就是非的意思。[^0-9]就表示 非[0-9]的任意字符,也就是,匹配不包含0123456789的其他任意字符。
但是,如果^寫到了[]的其他地方,也就是不在開頭時,它就表示它自己的字面意思了。
跟-一樣,雖然在不同位置能讓它的特殊功能失效,但是想要匹配其字面意思時,我還是建議大家對它進行轉義處理,也就是[\^]這樣。
(五) 總結
別問我為什么只有4個,請回去看看(一)里有幾個。
在正則表達式[]里面,主要有五個特殊字符:[]-\^,需要表達其字面意思時,最好都對它們進行轉義,而其他的任何字符,在[]都只能表達其字面意思。
因此,特別強調一個非常常見的錯誤寫法:[https|http]
有些人想要表達https或者http的意思,就寫了這個錯誤匹配,我們會發現,上面的式子其實等價[htps|],原因很簡單,[]是單字符匹配,而且里面的|只能表達其字面意思。對於這個例子的改正可以用下面兩種寫法: (https|http) 和 https?。 (https|http),利用了|字符 或 的意義,因為|的作用域是從左到右,直到遇到括號為止,因此,使用|的時候需要特別留意,一定要使用括號限定,否則又可能陷入另一個錯誤當中,如^https|http://,本來要表達^https://或^http://,卻得到了^https和http://。 https?,這個利用了?的0個或1個匹配的意義,如果s?匹配0個,那么就能匹配http,如果s?匹配1個,那么就能匹配https,從而達到預期目的。
更多關於正則表達式入門的內容,請參考本站博客《我眼里的正則表達式入門教程》
更多關於正則表達式高級的內容,請參考本站博客《深入講解正則表達式高級教程》
Windows正則表達式測試工具請從《正則表達式測試工具RegexBuddy-4.1.0》下載
Mac正則表達式測試工具請從《Mac正則表達式測試工具》下載
