《正則表達式經典實例(第2版)》——2.4 匹配任意字符
本節書摘來自異步社區《正則表達式經典實例(第2版)》一書中的第2章,第2.4節,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看
2.4 匹配任意字符
本實例講解點號元字符的使用和原理。
問題描述
匹配一個被單引號包圍的字符。第一種解決方案允許在引號之間出現除了換行符之外的任意單個字符。第二種解決方案允許出現任意字符,包括換行符在內。
解決方案
除了換行符之外的任意字符
'.'
正則選項:無(“點號匹配換行符”選項必須關閉)
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
包含換行符在內的任意字符
'.'
正則選項:點號匹配換行符
正則流派:.NET、Java、PCRE、Perl、Python、Ruby
'[\s\S]'
正則選項:無
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
討論
除了換行符之外的任意字符
點號是最古老也是最簡單的正則表達式特性之一。它的含義永遠是匹配任意單個字符。
然而,對於任意字符到底意味著什麼則存在一些混淆。用來處理正則表達式的最古老的工具在處理文件時是逐行處理的,因此,在目標文本中從來不可能出現包含換行符的情形。在本書中討論的編程語言則會把目標文本當作一個整體來處理,而不去管其中到底會包含多少個換行符。如果想要使用真正的逐行處理,就必須編寫一些代碼來把目標文本分割成包含單個文本行的數組,然後把正則表達式應用到該數組中的每行之上。下一章中的實例3.21會講解這樣做的方法。
Perl語言的開發者Larry Wall希望Perl能夠保留基於文本行的工具的傳統行為,也就是點號不會匹配換行符(\n)。本書中討論的所有其他流派也都采取了相同的策略。因此,‹.›會匹配除了換行字符之外的任意單個字符。
包含換行符在內的任意字符
如果確實想允許你的正則表達式可以跨越多個文本行,就需要打開“點號匹配換行符”的選項。這個選項可能會存於不同的名稱之下。Perl以及許多其他流派會把它稱作“單行”(single line)模式,這聽起來有些讓人摸不著頭腦;而在Java中則把它稱為“dot all”模式。下一章中的實例3.4會介紹所有的細節。不管在你所喜愛的編程語言中這個選項所用的名稱是什麼,都可以把它當作是“點號匹配換行符”模式。因為這就是該選項的確切含義。
而對於JavaScript來說,就需要使用另外一種解決方案,因為在其中並不包含“點號匹配換行符”的選項。按照在實例2.3中的講解,‹\s›會匹配任意空白字符,‹\S›而則會匹配‹\s›不能匹配的任意字符。把這二者組合起來構成‹[\s\S]›,這樣就會得到一個包含所有字符的字符組,其中也包含了換行符。類似的,‹[\d\D]›和‹[\w\W]›也會產生同樣的效果。
點號的濫用
點號是最經常被濫用的正則表達式特性。例如,‹\d\d.\d\d.\d\d›並不是用來匹配日期的好方法。它的確會匹配到05/16/08,但是它同時也會匹配99/99/99。更為甚者,它還會匹配12345678。
如何使用一個正則表達式來隻匹配合法的日期會在後麵的章節中講解(閱讀實例4.5)。顯然把點號替換成一個更合適的字符組是非常容易的。‹\d\d[/.-]\d\d[/.-]\d\d›允許使用斜杠、點號或者連字符來作為日期分隔符。這個正則表達式還是會匹配99/99/99,但是至少不會再匹配12345678。
雖然在前麵的例子中,字符組之內包含了一個點號,但這隻是一個巧合。事實上,在字符組之內,點號就是一個字麵字符。在上麵這個正則表達式中之所以會包含點號,是因為在一些國家(如德國),點號會被用來作為日期分隔符。
最好隻有當你確實想要允許出現任意字符時,才使用點號。而在任何其他場合,都應當使用一個字符組或者是排除型字符組。
變體
下麵是如何用內聯模式修飾符匹配引號內包括換行符在內的任意字符:
(?s)'.'
正則選項:無
正則流派:.NET、Java、XRegExp、PCRE、Perl、Python
(?m)'.'
正則選項:無
正則流派:Ruby
如果在正則表達式之外無法啟用“點號匹配換行符”模式,那麼你可以在正則表達式的開始處放一個模式修飾符。在實例2.1中的“不區分大小寫的匹配”小節中,我們已經介紹了模式修飾符的概念,並且也知道了JavaScript不支持此特性。
在 .NET、Java、XRegExp、PCRE、Perl和Python中,‹(?s)›是用於“點號匹配換行符”模式的模式修飾符。這裏的s代表的是“single line”(單行)模式,也就是在Perl中給“點號匹配換行符”所起的令人很容易混淆的名字。
最後更新:2017-06-06 07:35:24