閱讀129 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《正則表達式經典實例(第2版)》——2.5 匹配文本行起始和或文本行結尾

本節書摘來自異步社區《正則表達式經典實例(第2版)》一書中的第2章,第2.5節,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.5 匹配文本行起始和或文本行結尾

問題描述
分別創建4個正則表達式。匹配單詞alpha,僅限於它出現在目標文本最開始的時候。匹配單詞omega,僅限於它出現在目標文本結尾處的時候。匹配單詞begin,僅限於它出現在文本行開始處的時候。匹配單詞end,僅限於它出現在文本行結尾的時候。

解決方案
目標文本的開始

^alpha
正則選項:無(“^和$匹配換行處”選項必須關掉)
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python
\Aalpha
正則選項:無
正則流派:.NET、Java、PCRE、Perl、Python、Ruby

目標文本的結尾

omega$
正則選項:無(“^和$匹配換行處”選項必須關掉)
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python
omega\Z
正則選項:無
正則流派:.NET、Java、PCRE、Perl、Python、Ruby

行開始

^begin
正則選項:^和$匹配換行處
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

行結尾

end$
正則選項:^和$匹配換行處
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

討論
定位符和行
正則表達式記號‹^›、‹$›、‹\A›、‹\Z›和‹\z›被稱作是定位符(anchor)。它們並不匹配任意字符。事實上,它們匹配的是特定的位置,也就是說把正則表達式瞄準這些位置來進行匹配。

行指的是位於目標文本的開始和第一個換行符、在兩個換行符之間或者在最後一個換行符和目標文本結尾之間的那部分目標文本。如果在目標文本中不包含換行符的話,則整體目標文本就會被認為是一行。因此,下麵的文本包含有4行,分別是one、two、一個空串和four。

one
two
four

這個文本可以在程序中采用如下的表示:oneLFtwoLF LFfour。

目標文本的起始
定位符‹\A›總是會匹配目標文本的最開始處,也就是在第一個字符的前麵。這也是它會匹配的唯一位置。可以把‹\A›放到你的正則表達式的開始處,這樣就可以檢查目標文本是否是由你想要匹配的文本來開頭的。注意這裏的“A”必須是大寫的。

JavaScript不支持‹\A›。

定位符‹^›與‹\A›是等價的,前提是不能打開“^ 和$匹配換行處”這個選項。對於除了Ruby之外的所有其他正則流派來說,該選項都是默認關閉的。但是要記住在Ruby中並沒有提供可以關掉這個選項的方法。

除非你使用的是JavaScript,否則推薦總是使用‹\A›,而不是‹^›。‹\A›的含義始終保持不變,因此可以避免由於正則選項設置而造成的混淆或錯誤。

目標文本的結尾
定位符‹\Z›和‹\z›總是會匹配目標文本的結尾處,也就是說在最後一個字符之後。把‹\Z›或‹\z›放到正則表達式的結尾處,就可以測試是否目標文本會以你想要匹配的文本來作為結束。

.NET、Java、PCRE、Perl和Ruby同時支持‹\Z›和‹\z›。Python隻支持‹\Z›。JavaScript則根本不提供對‹\Z›或‹\z›的支持。

‹\Z›和‹\z›的唯一區別是當目標文本的最後一個字符是換行符的時候。在這種情形下,‹\Z›可以匹配目標文本的最結尾處,也就是在最後的換行符之後的位置,同時也可以匹配緊跟在這個換行符之前的位置。這樣做的好處是,你可以放心地搜索‹omega\Z›,而不必擔心在你的目標文本的最後是不是會存在一個多餘的換行符。當逐行讀入一個文件的時候,有些工具會包含行末的換行符,而有些工具則不然;‹omega\Z›會把這種區別隱藏起來。‹\z›則隻會匹配目標文本的最末尾處,因此如果存在一個多餘換行符的話,它就無法匹配。

定位符‹$›與‹\Z›是等價的,前提是不要打開“^和$匹配換行處”這個選項。對於除了Ruby之外的所有其他正則流派來說,該選項都是默認關閉的。而且在Ruby中並沒有提供可以關掉這個選項的方法。正像‹\Z›一樣,‹$›也會匹配目標文本的最末尾處,以及(如果存在的話)在最後一個換行符之前的位置。

為了幫助你更好地理解這裏的細微差別,我們來看一個Perl中的例子。假設$/(當前記錄分隔符)被設置為缺省的\n,那麼下麵的Perl語句會從終端(標準輸入)讀入一行:

$line = <>;
Perl會在變量$line的內容中保留換行符。因此,采用像‹end●of●input.\z›這樣的表達式就無法匹配該變量。而如果使用‹end●of●input.\Z›和‹end●of●input.$›則都可以匹配,因為它們會忽略後麵多餘的換行。

為了方便起見,Perl程序員通常會使用下麵的命令來去掉換行符:

chomp $line;
在執行了上述操作之後,上麵所給的3種定位符都會匹配。(嚴格來說,chomp會從當前字符串中抽掉記錄的分隔字符。)

除非你使用的是JavaScript,否則推薦你總是使用‹\Z›,而不是‹$›。‹\Z›的含義始終保持不變,因此可以避免由於正則選項設置而造成的混淆或錯誤。

文本行開始
默認情況下,‹^›隻會匹配目標文本的開始處,就像‹\A›一樣。隻有在Ruby中,‹^›才會總是匹配一行的開始位置。所有其他流派都要求打開一個選項來使得^和$這兩個符號可以匹配換行處。這個選項通常被稱作是“多行”(multiline)模式。

千萬別把這個模式同“單行”模式搞混,因為單行模式最好應該還是被稱作是“點號匹配換行符”模式。“多行”模式隻會影響到^和$這兩個符號,而“單行”模式則隻會影響到點號(如實例2.4所示)。你完全可以同時打開“單行”和“多行”模式。在默認情況下,這兩個選項都是關閉的。

在設置了正確的選項之後,‹^›就可以匹配目標文本中每行的開始。嚴格來講,它匹配文件中第一個字符之前的位置,以及在目標文本中每個換行符之後的位置。使用‹\n^›是多餘的,因為‹^›始終會匹配‹\n›之後的位置。

文本行結束
默認情況下,‹$›隻會匹配目標文本的結尾處或者是最後一個換行之前的位置,就像‹\Z›一樣。隻有在Ruby中,‹$›才會總是匹配一行的結尾處。所有其他流派都要求你打開“多行”模式來使得^和$這兩個符號可以匹配換行處。

在設置了正確的選項之後,‹$›會匹配目標文本中每行的結束。(當然,它同樣會匹配目標文本中的最後一個字符之後的位置,因為這個位置也總是一行的結束。)使用‹$\n›是多餘的,因為‹$›總是會匹配‹\n›之前的位置。

長度為0的匹配
對於一個正則表達式來說,它完全可以隻包含一個或者多個定位符。這樣一個正則表達式會在定位符能夠匹配的每個位置查找一個長度為0的匹配。如果把多個定位符放在一起的話,隻有當所有的定位符都在同一個位置匹配的時候,該正則式才會匹配成功。

可以在查找和替換的功能中使用這樣的正則表達式。可以通過替換‹\A›或‹\Z›來在整體目標文本之前或者之後添加一些內容。也可以通過在“^和$匹配換行處”的模式下,替換‹^›或‹$›,在目標文本的每行之前或者之後添加一些內容。

把兩個定位符組合起來則可以檢查空行或者缺失的輸入。‹\A\Z›會匹配空串,以及包含單個換行符的字符串。‹\A\z›則隻能匹配空串。在“^和$匹配換行處”的模式下,‹^$›會匹配目標文本中的每個空行。

變體

(?m)^begin
正則選項:無
正則流派:.NET、Java、XRegExp、PCRE、Perl、Python
(?m)end$
正則選項:無
正則流派:.NET、Java、XRegExp、PCRE、Perl、Python

如果不能在正則表達式之外打開“^和$匹配換行處”的模式,也可以在正則表達式之前使用一個模式修飾符來達到相同的效果。在實例2.1中的“不區分大小寫的匹配”一節中,我們已經講解了模式修飾符的概念,並且了解了JavaScript並不對此提供支持。

在.NET、Java、XRegExp、PCRE、Perl和Python中,‹(?m)›是“^和$匹配換行處”模式的模式修飾符。其中的m指的是“多行”(multiline)模式,這個是在Perl中引入的用來描述“^和$匹配換行處”模式的名稱,實在很容易讓人感到混淆。

如前所述,這個術語實在是太容易讓人弄混了,以致Ruby正則引擎的開發者都無法正確地遵循這種記法。在Ruby中使用‹(?m)›來打開“點號匹配換行符”模式。因此Ruby中的‹(?m)›與脫字符和美元符號都不存在任何關係。在Ruby中,‹^›和‹$›總是會匹配每一行的開始和結束。

除了令人遺憾的字母使用混淆之外,Ruby選擇使用‹^›和‹$›隻匹配每行是非常正確的。除非你使用的是JavaScript,我們推薦你在自己的正則表達式中都采用這種方式。

在Jan Goyvaerts設計EditPad Pro和PowerGREP的時候,他遵循了相同的想法。在這些工具中找不到關於“^和$匹配換行處”的複選框,雖然其中有個複選框的說明是“點號匹配新行”(dot matches newlines.)。除非在正則表達式之前添加了‹(?-m)›,否則就不得不使用‹\A›和‹\Z›來定位文件的開始和結束。

最後更新:2017-06-02 19:35:20

  上一篇:go  重磅│馬斯克首次全麵公布火星計劃細節,除了大火箭大飛船,還有太空加油
  下一篇:go  小紮曝Facebook北極數據中心圖片 最先進數據中心都建在哪?