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