《正则表达式经典实例(第2版)》——2.6 匹配完整单词
本節書摘來自異步社區《正則表達式經典實例(第2版)》一書中的第2章,第2.6節,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章節內容可以訪問云棲社區“異步社區”公眾號查看
2.6 匹配完整單詞
問題描述
創建一個正則表達式來匹配My cat is brown中的cat,同時不能匹配category或是bobcat。再創建一個正則表達式來匹配staccato中的cat,同時不能匹配到上面的3個目標字串。
解決方案
單詞邊界
非單詞邊界
\Bcat\B 正則選項:無 正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby討論
單詞邊界
正則表達式記號?b?被稱作是單詞邊界(word boundary)。它會匹配一個單詞的開始或結束。就它自身而言,所產生的是一個長度為0的匹配。?b?也是一個定位符,這與在前一個小節中介紹過的記號是一樣的。
嚴格來講,?b?會匹配如下3種位置:
在目標文本的第一個字符之前,如果第一個字符是單詞字符;
在目標文本的最后一個字符之后,如果最后一個字符是單詞字符;
在目標文本的兩個字符之間,其中一個是單詞字符,而另外一個不是單詞字符。
如果要使用正則表達式來進行“只匹配完整單詞”的查找,那么只需要把該單詞放在兩個單詞邊界之間,就像我們前面給出的?bcatb?。第一個?b?要求?c?出現在字符串的最開始處,或者是在一個非單詞字符后面。第二個?b?要求?t?出現在字符串的最末尾處,或者是在一個非單詞字符前面。換行符被認為是非單詞字符。如果換行符緊跟在一個單詞字符后面,那么?b?會匹配換行符后面的位置。它同樣會匹配緊跟著一個單詞字符之前的換行符。這樣的話,一個占據了一整行的單詞也可以通過一個“只匹配完整單詞”的查找來發現。?b?不會受到“多行”模式或是?(?m)?的影響,這也是本書把“多行”模式稱為“^和$匹配換行處”的原因之一。
本書中介紹的所有流派都不提供可以只匹配單詞之前或者只匹配單詞之后的單獨記號。除非想要創建一個正則式只包含單詞邊界,而不包含任何其他內容,否則這些單獨記號是不必要的。在正則表達式中,位于?b?之前和之后的記號會決定?b?可以匹配的位置。在?bx?和?!b?中的?b?只會匹配一個單詞的開始。而在?xb?和?b!?中的?b?只會匹配一個單詞的結束。?xbx?和?!b!?則永遠不會匹配任何位置。
如果確實只想匹配一個單詞之前或之后的位置,可以使用順序環視(lookahead)和逆序環視(lookbehind)。實例2.16講解了順序環視和逆序環視。這種方法無法在JavaScript和Ruby 1.8中使用,因為它們不支持逆序環視。正則式?(?
非單詞邊界
?B?會匹配在目標文本中?b?不匹配的每一個位置。換句話說,?B?會匹配不屬于單詞開始或結束的每一個位置。
嚴格來講,?B?匹配如下5個位置:
在目標文本的第一個字符之前,如果第一個字符不是單詞字符;
在目標文本的最后一個字符之后,如果最后一個字符不是單詞字符;
在兩個單詞字符之間;
在兩個非單詞字符之間;
空串。
?BcatB?會匹配staccato中的cat。但是不會匹配My cat is brown、category或者bobcat中的cat。
如果想要進行與“只匹配完整單詞”相反的查找(也就是說,不包括My cat is brown,但是包括staccato、category和bobcat),就需要采用多選結構來把?Bcat?和?catB?組合成為?Bcat|catB?。其中,?Bcat?會匹配staccato和bobcat中的cat。?catB?會匹配category中的cat(如果?Bcat?沒有匹配到,那么它也可以匹配staccato)。實例2.8會詳細講解多選結構。
單詞字符
我們前面一直在講單詞邊界,但是卻沒有涉及什么是單詞字符(word character)。單詞字符就是可以在單詞中出現的字符。在實例2.3中的“簡寫”小節中,我們討論了哪些字符是包含在?w?中的,即單個的單詞字符。但是,對于?b?來說情形則有些不同。
雖然本書中的所有流派都支持?b?和?B?,但是它們對于到底哪些字符屬于單詞字符則有所不同。
在.NET、JavaScript、PCRE、Perl、Python和Ruby中,?b?都會匹配兩個字符之間的位置,其中一個字符可以由?w?匹配,而另外一個字符則可以由?W?匹配。?B?則總是匹配同時被?w?或?W?匹配的兩個字符之間的位置。
JavaScript、PCRE和Ruby只把ASCII字符看做是單詞字符。?w?因此與?[a-zA-Z0-9_]?是完全等同的。在這些流派中,你可以對像英語這樣的,單詞完全由不含讀音符號的A到Z的字母組成的情況,進行“只匹配完整單詞”的查找。但是這些流派對于其他語言,如西班牙語或俄語,就無法進行“只匹配完整單詞”的查找。
.NET把所有語言字母表中的字母和數字都當作單詞字符。你可以對任意語言中的單詞進行“只匹配完整單詞”的查找,這其中也包括不使用拉丁字母的語言。
Python則為你提供了一個選項。在Python 2.x中,只有在創建正則式時傳遞了UNICODE或是U標志,非ASCII的字符才會被包括進來。在Python 3.x中,則默認包含非ASCII字符,不過可以使用ASCII或A標志排除它們。這些標志會對?b?和?w?產生相同的影響。
在Perl中,則Perl的版本和/adlu標志決定?w?是純ASCII字符還是包括全部Unicode字母、數字和下劃線。實例2.3“簡寫”一節講解了更多細節。在所有的Perl版本中,?b?與?w?保持一致。
Java則表現得不是很一致。在Java 4到Java 6中,?w?只匹配ASCII字符。在Java 7中,?w?默認值匹配ASCII字符,如果設置了UNICODE_CHARACTER_CLASS標志則也匹配Unicode字符。但是Java所有版本?b?都是支持Unicode的,包括任何字母表。在Java 4到Java 6中,?bwb?會匹配一個單個的英語字母、數字或是在任何語言中都不會作為單詞一部分出現的下劃線。?bкошкаb?會正確匹配cat在俄語中對應的單詞,因為?b?是支持Unicode的。但是?w+?不會匹配任何泰國語單詞,因為在Java 4到Java 6中?w?只會匹配ASCII字符。
總結
以上是生活随笔為你收集整理的《正则表达式经典实例(第2版)》——2.6 匹配完整单词的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3950双层交换机生成树协议
- 下一篇: 透过微信应用号,看HTML5与Nativ