溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何提升正則表達(dá)式運(yùn)行效率

發(fā)布時(shí)間:2021-09-28 17:29:04 來(lái)源:億速云 閱讀:137 作者:小新 欄目:互聯(lián)網(wǎng)科技

這篇文章給大家分享的是有關(guān)如何提升正則表達(dá)式運(yùn)行效率的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

如果純粹是為了挑戰(zhàn)自己的正則水平,用來(lái)實(shí)現(xiàn)一些特效(例如使用正則表達(dá)式計(jì)算質(zhì)數(shù)、解線性方程),效率不是問(wèn)題;如果所寫(xiě)的正則表達(dá)式只是為了滿足一兩次、幾十次的運(yùn)行,優(yōu)化與否區(qū)別也不太大。但是,如果所寫(xiě)的正則表達(dá)式會(huì)百萬(wàn)次、千萬(wàn)次地運(yùn)行,效率就是很大的問(wèn)題了。

 為行文方便,先定義兩個(gè)概念。
誤匹配:指正則表達(dá)式所匹配的內(nèi)容范圍超出了所需要范圍,有些文本明明不符合要求,但是被所寫(xiě)的正則式“擊中了”。例如,如果使用\d{11}來(lái)匹配11位的手機(jī)號(hào),\d{11}不單能匹配正確的手機(jī)號(hào),它還會(huì)匹配98765432100這樣的明顯不是手機(jī)號(hào)的字符串。我們把這樣的匹配稱之為誤匹配。
漏匹配:指正則表達(dá)式所匹配的內(nèi)容所規(guī)定的范圍太狹窄,有些文本確實(shí)是所需要的,但是所寫(xiě)的正則沒(méi)有將這種情況囊括在內(nèi)。例如,使用\d{18}來(lái)匹配18位的身份證號(hào)碼,就會(huì)漏掉結(jié)尾是字母X的情況。
寫(xiě)出一條正則表達(dá)式,既可能只出現(xiàn)誤匹配(條件寫(xiě)得極寬松,其范圍大于目標(biāo)文本),也可能只出現(xiàn)漏匹配(只描述了目標(biāo)文本中多種情況種的一種),還可能既有誤匹配又有漏匹配。例如,使用\w+\.com來(lái)匹配.com結(jié)尾的域名,既會(huì)誤匹配abc_.com這樣的字串(合法的域名中不含下劃線,\w包含了下劃線這種情況),又會(huì)漏掉ab-c.com這樣的域名(合法域名中可以含中劃線,但是\w不匹配中劃線)。
精準(zhǔn)的正則表達(dá)式意味著既無(wú)誤匹配且無(wú)漏匹配。當(dāng)然,現(xiàn)實(shí)中存在這樣的情況:只能看到有限數(shù)量的文本,根據(jù)這些文本寫(xiě)規(guī)則,但是這些規(guī)則將會(huì)用到海量的文本中。這種情況下,盡可能地(如果不是完全地)消除誤匹配以及漏匹配,并提升運(yùn)行效率,就是我們的目標(biāo)。本文所提出的經(jīng)驗(yàn),主要是針對(duì)這種情況。
掌握語(yǔ)法細(xì)節(jié)。正則表達(dá)式在各種語(yǔ)言中,其語(yǔ)法大致相同,細(xì)節(jié)各有千秋。明確所使用語(yǔ)言的正則的語(yǔ)法的細(xì)節(jié),是寫(xiě)出正確、高效正則表達(dá)式的基礎(chǔ)。例如,perl中與\w等效的匹配范圍是[a-zA-Z0-9_];perl正則式不支持肯定逆序環(huán)視中使用可變的重復(fù)(variable repetition inside lookbehind,例如(?<=.*)abc),但是.Net語(yǔ)法是支持這一特性的;又如,JavaScript連逆序環(huán)視(Lookbehind,如(?<=ab)c)都不支持,而perl和python是支持的?!毒ㄕ齽t表達(dá)式》第3章《正則表達(dá)式的特性和流派概覽》明確地列出了各大派系正則的異同,這篇文章也簡(jiǎn)要地列出了幾種常用語(yǔ)言、工具中正則的比較。對(duì)于具體使用者而言,至少應(yīng)該詳細(xì)了解正在使用的那種工作語(yǔ)言里正則的語(yǔ)法細(xì)節(jié)。
先粗后精,先加后減。使用正則表達(dá)式語(yǔ)法對(duì)于目標(biāo)文本進(jìn)行描述和界定,可以像畫(huà)素描一樣,先大致勾勒出框架,再逐步在局步實(shí)現(xiàn)細(xì)節(jié)。仍舉剛才的手機(jī)號(hào)的例子,先界定\d{11},總不會(huì)錯(cuò);再細(xì)化為1[358]\d{9},就向前邁了一大步(至于第二位是不是3、5、8,這里無(wú)意深究,只舉這樣一個(gè)例子,說(shuō)明逐步細(xì)化的過(guò)程)。這樣做的目的是先消除漏匹配(剛開(kāi)始先盡可能多地匹配,做加法),然后再一點(diǎn)一點(diǎn)地消除誤匹配(做減法)。這樣有先有后,在考慮時(shí)才不易出錯(cuò),從而向“不誤不漏”這個(gè)目標(biāo)邁進(jìn)。
留有余地。所能看到的文本sample是有限的,而待匹配檢驗(yàn)的文本是海量的,暫時(shí)不可見(jiàn)的。對(duì)于這樣的情況,在寫(xiě)正則表達(dá)式時(shí)要跳出所能見(jiàn)到的文本的圈子,開(kāi)拓思路,作出“戰(zhàn)略性前瞻”。例如,經(jīng)常收到這樣的垃圾短信:“發(fā)*票”、“發(fā)#漂”。如果要寫(xiě)規(guī)則屏蔽這樣煩人的垃圾短信,不但要能寫(xiě)出可以匹配當(dāng)前文本的正則表達(dá)式 發(fā)[*#](?:票|漂),還要能夠想到 發(fā).(?:票|漂|飄)之類可能出現(xiàn)的“變種”。這在具體的領(lǐng)域或許會(huì)有針對(duì)性的規(guī)則,不多言。這樣做的目的是消除漏匹配,延長(zhǎng)正則表達(dá)式的生命周期。
明確。具體說(shuō)來(lái),就是謹(jǐn)慎用點(diǎn)號(hào)這樣的元字符,盡可能不用星號(hào)和加號(hào)這樣的任意量詞。只要能確定范圍的,例如\w,就不要用點(diǎn)號(hào);只要能夠預(yù)測(cè)重復(fù)次數(shù)的,就不要用任意量詞。例如,寫(xiě)析取twitter消息的腳本,假設(shè)一條消息的xml正文部分結(jié)構(gòu)是<span class=”msg”>…</span>且正文中無(wú)尖括號(hào),那么<span class=”msg”>[^<]{1,480}</span>這種寫(xiě)法的思路要好于<span class=”msg”>.*</span>,原因有二:一是使用[^<],它保證了文本的范圍不會(huì)超出下一個(gè)小于號(hào)所在的位置;二是明確長(zhǎng)度范圍,{1,480},其依據(jù)是一條twitter消息大致能的字符長(zhǎng)度范圍。當(dāng)然,480這個(gè)長(zhǎng)度是否正確還可推敲,但是這種思路是值得借鑒的。說(shuō)得狠一點(diǎn),“濫用點(diǎn)號(hào)、星號(hào)和加號(hào)是不環(huán)保、不負(fù)責(zé)任的做法”。
不要讓稻草壓死駱駝。每使用一個(gè)普通括號(hào)()而不是非捕獲型括號(hào)(?:…),就會(huì)保留一部分內(nèi)存等著你再次訪問(wèn)。這樣的正則表達(dá)式、無(wú)限次地運(yùn)行次數(shù),無(wú)異于一根根稻草的堆加,終于能將駱駝壓死。養(yǎng)成合理使用(?:…)括號(hào)的習(xí)慣。
寧簡(jiǎn)勿繁。將一條復(fù)雜的正則表達(dá)式拆分為兩條或多條簡(jiǎn)單的正則表達(dá)式,編程難度會(huì)降低,運(yùn)行效率會(huì)提升。例如用來(lái)消除行首和行尾空白字符的正則表達(dá)式s/^\s+|\s+$//g;,其運(yùn)行效率理論上要低于s/^\s+//g; s/\s+$//g; 。這個(gè)例子出自《精通正則表達(dá)式》第五章,書(shū)中對(duì)它的評(píng)論是“它幾乎總是最快的,而且顯然最容易理解”。既快又容易理解,何樂(lè)而不為?工作中我們還有其它的理由要將C==(A|B)這樣的正則表達(dá)式拆為A和B兩條表達(dá)式分別執(zhí)行。例如,雖然A和B這兩種情況只要有一種能夠擊中所需要的文本模式就會(huì)成功匹配,但是如果只要有一條子表達(dá)式(例如A)會(huì)產(chǎn)生誤匹配,那么不論其它的子表達(dá)式(例如B)效率如何之高,范圍如何精準(zhǔn),C的總體精準(zhǔn)度也會(huì)因A而受到影響。
巧妙定位。有時(shí)候,我們需要匹配的the,是作為單詞的the(兩邊有空格),而不是作為單詞一部分的t-h-e的有序排列(例如together中的the)。在適當(dāng)?shù)臅r(shí)候用上^,$,\b等等定位錨點(diǎn),能有效提升找到成功匹配、淘汰不成功匹配的效率。

感謝各位的閱讀!關(guān)于“如何提升正則表達(dá)式運(yùn)行效率”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI