国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

正則與JS中的正則

firim / 1139人閱讀

摘要:注意本文將正則與中的正則分開討論。正則零寬斷言更多參考各種語言對(duì)于正則不同支持參考單行模式與多行模式通過設(shè)置正則表達(dá)式后的修飾符可開啟對(duì)應(yīng)的匹配模式單行模式和多行模式。

最近這段時(shí)間幫同學(xué)處理一些文檔, 涉及到一些結(jié)構(gòu)化文檔的工作大部分都得使用正則表達(dá)式, 之前對(duì)于正則的認(rèn)識(shí)大多來源于語言書上那幾頁的介紹, 自己也沒有用過幾次。這里將我之前感到模糊的概念作個(gè)整理。因?yàn)閷?duì)JS了解多點(diǎn),所以也將JS中相關(guān)的正則特性歸納下。注意本文將正則與JS中的正則分開討論。

正則引擎

正則表達(dá)式的解釋引擎只有兩種,字符驅(qū)動(dòng)(text-directed)和正則驅(qū)動(dòng)(regex-directed),基于這兩種解釋引擎算法的不同,它們有時(shí)也被稱為DFA(Deterministic finite automaton 確定型有窮自動(dòng)機(jī))與NFA(Non-deterministic finite automaton非確定型有窮自動(dòng)機(jī)),當(dāng)前大部分現(xiàn)代語言的正則解釋器采用“正則驅(qū)動(dòng)”引擎,這是因?yàn)镹FA運(yùn)行的回溯算法可以實(shí)現(xiàn)諸如‘惰性匹配(lazy quantifiers )’和‘后部引用(backreferences)’ 等非常有用的特性, 而DFA算法也就是字符驅(qū)動(dòng)型引擎并不支持這些特性,當(dāng)然復(fù)雜的算法必須付出性能的代價(jià),字符驅(qū)動(dòng)引擎的性能要強(qiáng)于正則驅(qū)動(dòng)。各種語言中由于實(shí)現(xiàn)正則引擎的具體算法以及調(diào)用的正則庫都有不同,所以對(duì)于正則的支持也不同,關(guān)于這些概念的參考mark在這里:
?Regex Engine Internals
?正則表達(dá)式匹配解析過程探討分析(正則表達(dá)式匹配原理)

零寬斷言

零寬斷言(zero-length assertions)這概念直譯過于術(shù)語化(都有點(diǎn)像咒語了,囧rz), 邏輯不是太復(fù)雜,但是容易混淆模糊,在此記個(gè)筆記。零寬的意思是指該位置是不占寬度的,也就是只作斷言判斷,但不匹配實(shí)際的內(nèi)容,比如d(?=.)這個(gè)正向先行斷言(這概念也歸納在后)就只匹配點(diǎn)號(hào)之前的數(shù)字,但是它并不會(huì)匹配到這個(gè)點(diǎn)號(hào),這個(gè)d(?=.)括號(hào)中的匹配內(nèi)容也就是零寬了。
零寬斷言分為四種,分別是:正向先行(Positive Lookahead),正向回顧(Positive Lookbehind),負(fù)向先行(Negative Lookahead),負(fù)向回顧(Negative Lookbehind)。正向和負(fù)向的意思是斷言括號(hào)中的內(nèi)容是匹配還是不匹配,比如上面栗子?中的(?=...)就是正向先行斷言的寫法,該斷言括號(hào)中的內(nèi)容必須出現(xiàn), 而負(fù)向也就是斷言括號(hào)中的內(nèi)容不能出現(xiàn),負(fù)向先行的寫法是這樣:(?!...)。 先行與回顧的意思是實(shí)際匹配的內(nèi)容在斷言內(nèi)容的前面還是后面,以下將逐一羅列這四種概念:

正向先行

直接地說“零寬正向先行斷言”所匹配的就是必須出現(xiàn)的斷言內(nèi)容的前面的內(nèi)容,之前的點(diǎn)號(hào)前數(shù)字的栗子?d(?=.)已經(jīng)比較直觀的展示了這個(gè)概念,但是需要注意的是:這里的先行或者回顧是基于位置,而不是字符!也就是說從點(diǎn)號(hào)的位置開始向前匹配, 比如我們把這個(gè)正則表達(dá)式改成這樣:(?=.).注意這里并沒有把實(shí)際要匹配的內(nèi)容放在斷言括號(hào)的前面,而是放到了后面, 這就匹配了從這個(gè)點(diǎn)號(hào)位置開始的任意字符(除換行符外),也就匹配到了這個(gè)點(diǎn)號(hào), 當(dāng)然通常這樣寫沒什么意義, 但便于理解位置的含義。

正向回顧

理解了前面這個(gè)“零寬正向先行斷言”,隨之而來的就比較好理解了。依照這個(gè)邏輯,零寬正向回顧斷言所匹配的是必須出現(xiàn)的斷言內(nèi)容之后的內(nèi)容,它的語法是:(?<=...) 比如(?<=.)w所匹配的就是點(diǎn)號(hào)之后的ASCII字符。

負(fù)向先行

負(fù)向與正向意思相反, 正向是斷言內(nèi)容必須出現(xiàn),而負(fù)向則是斷言內(nèi)容必須不出現(xiàn)。比如JavaScript and Java這句話中使用Java(?!Script)就只會(huì)匹配到Java,因?yàn)樵撜齽t斷言Java后面不能出現(xiàn)Script

負(fù)向回顧

正負(fù)向與先行回顧的概念都已在前面列出, 負(fù)向回顧的理解應(yīng)該就很順了。負(fù)向回顧的語法是:(?。 比如(?該正則只匹配不是JavaScriptScript,它就能正確匹配ECMAScriptScript。

這里需要注意:在大多數(shù)語言中,先行斷言中可以有任意的正則語法,比如可以用+或者*這種不確定重復(fù)的匹配,但是回顧斷言中的限制就比較多,很多語言的回顧斷言中不支持諸如+*這種不定重復(fù)的匹配和后部引用,因?yàn)檎齽t解釋引擎在匹配回顧斷言的時(shí)候,當(dāng)回顧斷言中的內(nèi)容匹配成功后再去匹配斷言后的實(shí)際內(nèi)容時(shí),它需要能計(jì)算出后退多少步才能判斷出當(dāng)前匹配是否與這個(gè)正則完全匹配。有些語言壓根就不支持回顧斷言,比如JS;而 PHP, Delphi, R和 Ruby只支持在回顧斷言中加入選擇匹配,但選擇匹配的內(nèi)容長度必須相同,形如[ab|ba|cd];Java回顧斷言限制不多,但無法在回顧斷言中加入不定數(shù)量的重復(fù),也就是不能在回顧斷言中使用+; .Net支持在回顧斷言中使用任意正則語法。(以上內(nèi)容參考自下面的第一個(gè)mark參考中,可能存在時(shí)效的問題, 如有錯(cuò)誤還請(qǐng)大神指出。

正則零寬斷言更多參考mark:
?Lookahead and Lookbehind Zero-Length Assertions

各種語言對(duì)于正則不同支持參考:
?Comparison of regular expression engines

單行模式與多行模式

通過設(shè)置正則表達(dá)式后的修飾符(flag)可開啟對(duì)應(yīng)的匹配模式:s(單行模式)和m(多行模式)。單行模式與多行模式這兩名字容易讓人誤以為兩者是互相排斥的, 也就是誤以為開啟了多行模式,那么就不是單行模式,而實(shí)際上單行模式或多行模式的開關(guān)并不會(huì)影響另一個(gè),兩個(gè)模式可以同時(shí)用。

單行模式

開關(guān)單行模式影響的是元字符.的匹配。單行模式開啟時(shí),元字符.匹配包括換行符 在內(nèi)的任意字符,單行模式關(guān)閉時(shí),元字符.匹配不包括換行符 的任意字符。

多行模式

多行模式影響的是元字符^$。多行模式開啟時(shí),元字符^可以匹配字符串開頭(字符串的開始位置),也可以匹配行的開頭(即換行符 之后的位置),元字符$ 可以匹配字符串結(jié)尾(字符串的結(jié)束位置), 也可以匹配行的結(jié)尾(即換行符 之前的位置)。多行模式關(guān)閉時(shí),元字符^$只能匹配字符串的開頭和結(jié)尾,不能匹配換行符 的之前和之后。也就是說如果沒有這兩個(gè)元字符,即使正則后加多行模式修飾符m也無意義,多行模式的正則必須有這兩個(gè)元字符中的一個(gè)或兩個(gè)才有意義。
概念參考mark: ?正則表達(dá)式的多行模式與單行模式
附一個(gè)JS描述的多行模式:?multiline 屬性(正則表達(dá)式)(JavaScript)

注意:JS中正則并不支持單行模式的開啟

JS中的正則

JS中的正則需要注意下正則對(duì)象的方法與String對(duì)象方法的微妙區(qū)別。

RegExp對(duì)象

每個(gè)正則對(duì)象實(shí)例有這幾項(xiàng)屬性global(是否帶有修飾符g的布爾值) ignoreCase(是否帶有修飾符i的布爾值) lastIndex(對(duì)象方法匹配開始的位置索引,初始為0) multiline(是否帶有修飾符m的布爾值) source(正則源碼文本,注意源碼文本不包括修飾符)。

ES6中RegExp對(duì)象實(shí)例新增的只讀屬性sticky可以判斷正則后是否帶修飾符y(新增),設(shè)置y修飾符的正則每次匹配,存在lastIndex屬性情況下lastIndex不會(huì)自動(dòng)歸零,并且在正則表達(dá)式中隱式地加入了開頭元字符^,這樣就使得正則表達(dá)式的匹配錨定在lastIndex的位置。這種用法的詳情可參考MDN文檔的栗子?:?RegExp.prototype.sticky 以及?JavaScript:正則表達(dá)式的/y標(biāo)識(shí)

JS中每個(gè)RegExp對(duì)象實(shí)例有兩個(gè)方法,分別是:exec()test()。這兩個(gè)方法運(yùn)行邏輯幾乎等價(jià),但是exec要復(fù)雜些,匹配失敗返回null,匹配成功它將返回一個(gè)數(shù)組, 數(shù)組第一個(gè)元素是匹配整個(gè)正則的內(nèi)容,之后的元素是正則中捕獲組的匹配(注:使用非捕獲組可以獲得微弱的性能優(yōu)勢(shì))舉個(gè)栗子:

//捕獲組()
var pattern1 = /(www).(baidu).(com)/i  
//非捕獲組(?:)
var pattern2 = /(?:www).(?:baidu).(?:com)/i

var str  = "www.baidu.com"

pattern1.exec(str)
//返回?cái)?shù)組["www.baidu.com", "www", "baidu", "com"]
pattern2.exec(str)
//返回?cái)?shù)組["www.baidu.com"]

注意:雖然exec()和String的match()方法返回的都是數(shù)組的實(shí)例,但是他們的返回值都有兩個(gè)額外的屬性:indexinput分別表示匹配項(xiàng)在字符串中的位置和應(yīng)用正則的整段字符串。

test()方法更為簡(jiǎn)單,匹配成功返回true,失敗返回false。這里需要注意下這兩個(gè)方法中的lastIndex屬性與正則表達(dá)式中的全局修飾符g的關(guān)系。
當(dāng)正則中存在全局修飾符g時(shí),RegExp對(duì)象的lastIndex屬性將保存下一次開始的匹配的位置,比如:

var  pattern = /(www).(baidu).(com)/g 
var  str2 = "www.baidu.com www.google.com www.baidu.com"
pattern.exec(str2)
pattern.lastIndex  //13

這意味著下次調(diào)用exec方法它將從被匹配字符串索引13的位置開始匹配(也可以手動(dòng)設(shè)置lastIndex的值)。test()方法同理。正因?yàn)榇嬖跉埩舻膌astIndex,所以使用正則對(duì)象的方法可能會(huì)導(dǎo)致一些意外的結(jié)果,不過在ES5中,正則表達(dá)式直接量的每次計(jì)算都會(huì)創(chuàng)建一個(gè)RegExp對(duì)象實(shí)例,他們各自擁有l(wèi)astIndex,這就大大降低了意外的概率。
但是String對(duì)象中支持正則的方法卻與正則對(duì)象的方法不同,String方法忽略lastIndex,但是,如果存在全局修飾符g,string方法將有些許不同。

String中的正則方法

String方法中支持正則的有match(),replace(), search(),split()這四個(gè)方法。
match()方法接受一個(gè)字符串或正則作為參數(shù),當(dāng)參數(shù)是正則時(shí), 正則是否帶全局修飾符g將影響該方法的返回值,該方法匹配不帶全局修飾符的正則時(shí),與RegExp對(duì)象實(shí)例方法exec()的返回值一樣, 匹配帶全局修飾符的正則時(shí),match()方法將返回全局中所匹配到的所有內(nèi)容而不再將正則中的捕獲組編碼。比如前面的str2如果使用String的match方法的話其返回的數(shù)組中將是["www.baidu.com","www.baidu.com"]。

replace(searchValue,replaceValue)方法同樣接受字符串或正則作為第一個(gè)參數(shù),當(dāng)搜索值是字符串的時(shí)候,它只會(huì)匹配一次,很多時(shí)候這并非我們要的結(jié)果, 一般我們希望全局匹配,于是可以使用帶全局修飾符的正則表達(dá)式。replace()的替換值中的美元符號(hào)$有特殊含義,比如$1表示正則表達(dá)式中第一個(gè)捕獲組的匹配內(nèi)容。它的意義取自RegExp構(gòu)造函數(shù)的屬性(正則表達(dá)式每次的操作都會(huì)影響構(gòu)造函數(shù)RegExp的屬性,該構(gòu)造函數(shù)屬性的詳細(xì)參考可以看下《JS高級(jí)程序設(shè)計(jì)》中文第三版108頁中的說明)下面借用《JS權(quán)威指南》核心參考中的栗子。

var  name = "Doe,John"
name.replace(/(w+)*,(w+)/,"$2 $1")//$num代表捕獲組的編號(hào)
"John Doe"  

美元符號(hào)的特殊含義歸納:

$$ 替換對(duì)象$

$& 整個(gè)匹配的文本

$number 分組捕獲的文本(從1開始,不是0哦)

$` 匹配之前的文本

$" 匹配之后的文本

search()方法與String中indexOf類似,接受一個(gè)正則或者字符串為參數(shù),匹配成功返回第一個(gè)匹配的首字符位置, 失敗則返回-1。

split(separator,howmany)方法接受一個(gè)必選的分割位置作為第一個(gè)參數(shù),第二個(gè)參數(shù)設(shè)置返回?cái)?shù)組的最大長度。第一個(gè)參數(shù)可以是字符串或正則表達(dá)式,如果該參數(shù)是包含捕獲組(帶圓括號(hào)帶子表達(dá)式)的正則表達(dá)式,那么返回的數(shù)組中包括與這些子表達(dá)式匹配的字串(但不包括與整個(gè)正則表達(dá)式匹配的文本)
舉個(gè)例子?:

"hello world".split(/(w)s/)
//返回["hell", "o", "world"]

可以看到捕獲組中的匹配("o")也在返回的數(shù)組中,但是整個(gè)正則的匹配被作為分隔位置。并非所有瀏覽器都支持split()這個(gè)特性。
MDN文檔中并未說明該特性更多細(xì)節(jié):?String.prototype.split()

JS中不支持的正則特性

這里也順便轉(zhuǎn)貼一下《JS高級(jí)程序設(shè)計(jì)》第三版中提到的JS(ES5)正則的局限性:

匹配字符串開始的結(jié)尾的A和Z錨(但支持以^和$來匹配字符串的開始的結(jié)尾)

向后查找(但支持向前查找)

并集和交集類

原子組

Unicode支持(單個(gè)字符除外)

命名的捕獲組(但支持編號(hào)的捕獲組)

s(single單行)和x(free-spacing無間隔)匹配模式

條件匹配

正則表達(dá)式注釋

JS的正則庫

以上所提到的局限性中,可使用正則庫或多或少的抵消一些,比如XRegExp 調(diào)用該庫之后就可以使JS的正則支持可命名空間的捕獲組以及注釋等有用的特性, 關(guān)于JS的正則庫XRegExp,我寫了篇大致的介紹:?JavaScript正則庫:XRegExp

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/78274.html

相關(guān)文章

  • JS中的正則表達(dá)式

    摘要:構(gòu)造函數(shù)可以有兩個(gè)字符串參數(shù),第一個(gè)參數(shù)包含正則表達(dá)式的主體部分。只讀的布爾值,說明這個(gè)正則表達(dá)式是否帶有修飾符。中正則的擴(kuò)展構(gòu)造函數(shù)在中,只能接受字符串作為參數(shù),允許其直接接受正則表達(dá)式作為參數(shù)。 上文傳送門:初探正則表達(dá)式 正則表達(dá)式是一個(gè)描述字符模式的對(duì)象,JavaScript 的 RegExp 類表示正則表達(dá)式,String 和 RegExp 都定義了方法,后者使用正則表達(dá)式進(jìn)...

    Soarkey 評(píng)論0 收藏0
  • 正則表達(dá)式前端使用手冊(cè)

    摘要:非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。 導(dǎo)讀 你有沒有在搜索文本的時(shí)候絞盡腦汁, 試了一個(gè)又一個(gè)表達(dá)式, 還是不行. 你有沒有在表單驗(yàn)證的時(shí)候, 只是做做樣子(只要不為空就好), 然后燒香拜佛, 虔誠祈禱, 千萬不要出錯(cuò). 你有沒有在使用sed 和 grep 命令的時(shí)候, 感覺莫名其妙, 明明應(yīng)該支持的元字符, 卻就是匹配不到. 甚至,...

    zhoutao 評(píng)論0 收藏0
  • JS正則表達(dá)式元字符

    摘要:表示非單詞字符,等效于正則教程返回完整的字符串,因?yàn)?,中文算作是非單詞字符。行首行尾,修飾符形式修飾符的作用是修改和在正則表達(dá)式中的作用,讓它們分別表示行首和行尾。 正則 描述 正則 描述 f 匹配換頁符 匹配制表符 匹配換行符 v 匹配垂直制表符 匹配回車 s 匹配單個(gè)空格,等同于[f v]; S...

    CODING 評(píng)論0 收藏0
  • JavaScript正則表達(dá)式總結(jié)

    摘要:正則表達(dá)式一直是里比較難以掌握的點(diǎn)。在中創(chuàng)建正則的兩種方式使用字面量這就是正則表達(dá)式的字面量語法,表示正則表達(dá)式的模式,為正則表達(dá)式的標(biāo)志。字面量形式的正則表達(dá)式一般使用較多,也推薦大家盡可能使用這種形式,簡(jiǎn)潔易讀,符合正常的使用習(xí)慣。 正則表達(dá)式一直是js里比較難以掌握的點(diǎn)。 看不懂,學(xué)不會(huì),記不住。 每次需要用到正則的時(shí)候,都需要再去查找資料。 今天花時(shí)間把正則的知識(shí)點(diǎn)總結(jié)下,希望...

    big_cat 評(píng)論0 收藏0
  • js謎之正則表達(dá)式

    摘要:用正則表達(dá)式語言創(chuàng)建的。匹配非數(shù)字的字符使用元字符元字符在正則表達(dá)式中有特殊含義的字符。正則表達(dá)式默認(rèn)是區(qū)別大小寫的。正則表達(dá)式的字符串表示。若是一個(gè)正則表達(dá)式,若有標(biāo)志則替換所有匹配之處,若沒有則只替換第一個(gè)匹配之處。 前言 好久之前就說要寫一篇正則表達(dá)式的文章,正則表達(dá)式總是記了又忘,忘了再記,記了再忘,卒。言歸正傳,今天終于要研究一下這個(gè)謎一樣的正則表達(dá)式了。其實(shí)正則表達(dá)式并不難...

    wendux 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<