Learning notes for mastering RegEx

構(gòu)建掃描器程序的兩個(gè)重要方法

boolean hitEnd()

  • 返回true,說明結(jié)尾有更多的字符可能會(huì)改變本次的匹配結(jié)果(匹配成功變成失敗,失敗變成成功,或者匹配內(nèi)容發(fā)生改變)
  • 返回false,說明結(jié)尾有更多的字符不會(huì)改變本次的匹配結(jié)果

boolean requireEnd()
只有匹配成功該方法的返回值才有意義

  • 返回true,說明結(jié)尾有更多的字符可能會(huì)使得本次匹配失敗
  • 返回false,說明結(jié)尾有更多的字符不可能會(huì)使得本次匹配失敗,雖然可能會(huì)影響本次匹配的細(xì)節(jié),如匹配內(nèi)容發(fā)生改變

消除循環(huán)

(normal)*(special(normal)*)*

  • 防止special部分造成的循環(huán)

special要能寫成start(middle)*end

  1. start-endmiddle 匹配的是無交集的兩部分
  2. startend是固化的文本,且startend至少存在一部分,middle可不存在
  • start(middle)* 是為了防止此模式匹配成功后,外層(...)*表達(dá)式還能夠繼續(xù)匹配,導(dǎo)致內(nèi)部和外部遞歸匹配一段文本,加上start,當(dāng)middle回溯文本時(shí),外部無法再匹配內(nèi)部交還的文本
  • (middle)*end 是為了防止本次的匹配成功,如果本次不能匹配成功,那么外部也無法繼續(xù)應(yīng)用該表達(dá)式了,

  • 防止normal部分造成的循環(huán)

  • 把start看成special,middle看成normal,也就保證了(special(normal))不會(huì)造成無休止的匹配了,這是(start(middle)end)缺少end的一種形式

表達(dá)式的優(yōu)化

  • 對(duì)于(.*)(Suffix)這種以.*匹配優(yōu)先開始的表達(dá)式通常可以在開頭使用行開頭錨點(diǎn)標(biāo)記^,
    得到^(.*)(Suffix)

  • 這樣傳動(dòng)裝置只會(huì)在文本開頭應(yīng)用一次該表達(dá)式,因?yàn)槠ヅ鋬?yōu)先總是能夠匹配完全部的文本,當(dāng)(Suffix)匹配時(shí),會(huì)強(qiáng)迫之前的表達(dá)式歸還文本,所以如果能夠匹配成功,(Suffix)匹配的總是文本中最后一個(gè)滿足的匹配,以后的文本不存在能夠與(Suffix)相匹配的了,所以后面的嘗試都是多余的,而使用^行錨點(diǎn)標(biāo)記,傳動(dòng)裝置將不會(huì)做多余的嘗試.


  • 將結(jié)尾部分分散到多選結(jié)構(gòu)內(nèi),使用(?:com\b|edu\b|org\b|int\b|net\b|biz\b|coop\b|areo\b)而不使用(?:com|edu|org|int|net|biz|coop|areo)\b,后者每當(dāng)一個(gè)多選分支匹配成功后,將退出多選分支,但是在\b將失敗,此時(shí)又會(huì)回溯,如果將\b添加在多選結(jié)構(gòu)內(nèi),則在未退出多選結(jié)構(gòu)就能發(fā)現(xiàn)匹配失敗,這個(gè)優(yōu)化是有風(fēng)險(xiǎn)的,如果表達(dá)式是(?:this|that):則改(?:this:|that:)就違背了將獨(dú)立文本單獨(dú)出來的思想,任何的優(yōu)化都是平等的,可能會(huì)因小失大,
  • 考慮到如果是位置匹配之類的可以放入到多選結(jié)構(gòu)內(nèi),但是如果尾部是$,即行結(jié)尾標(biāo)記,則又將失去行結(jié)束錨點(diǎn)的優(yōu)化,也就是除了一些特殊的位置標(biāo)記,其他可以放入到多選結(jié)構(gòu)內(nèi),而一些單純的文本則不放入,將他們單獨(dú)分離出來,可以得到文本中必須出現(xiàn)字符或字符串優(yōu)化.

\G使用之前匹配結(jié)束的位置

  • regex = "\\G(?:\\d{5})*?(44\\d{3})?"
    如果使用該表達(dá)式匹配文本,一旦匹配的文本長度為0,則將不會(huì)在進(jìn)行匹配,因?yàn)槭褂玫氖侵捌ヅ浣Y(jié)束的位置,傳動(dòng)裝置將不會(huì)驅(qū)動(dòng),使用引擎能知道下次在該處匹配也得到相同的結(jié)果,會(huì)無限循環(huán)

匹配44開頭的5位數(shù)美國郵政編碼(ZIP Codes)

  • 目標(biāo)文本是類似這樣的
    03824531449411615213441829505344272752010217443235
  • 匹配的難題是在某次匹配失敗時(shí),傳動(dòng)裝置會(huì)驅(qū)動(dòng)前進(jìn)一個(gè)字符,再次進(jìn)行匹配,而如果此時(shí)的匹配成功顯然不是我們需要的,因?yàn)檫@個(gè)郵政編碼在數(shù)據(jù)中可能根本不存在,
  • 我使用的辦法是在進(jìn)行匹配的開始,要保證左邊必須是5的倍數(shù)數(shù)字,所以使用正則表達(dá)式(?<=^(?:\d{5})*)44\d{3},但這將使用逆序環(huán)視進(jìn)行掃描不定長度的文本,一些正則引擎可能不支持,
  • 另一個(gè)辦法是保證數(shù)據(jù)的協(xié)調(diào)性,出現(xiàn)匹配錯(cuò)誤數(shù)據(jù)的原因主要是傳動(dòng)裝置的驅(qū)動(dòng),導(dǎo)致了數(shù)據(jù)的錯(cuò)位,實(shí)際上如果不是從5的倍數(shù)的位置開始匹配,即使成功,也是沒有意義的數(shù)據(jù),所以可以使用一些表達(dá)式來跳過(匹配)不是44開頭的的5位數(shù)ZIP Codes

3個(gè)辦法

  • [1235-9]\d{4}|\d[1235-9]\d{3} (如果開頭44則失配)
  • (?!44)\d{5} (如果開頭不是44則匹配)
  • (\d{5}*?) 使用忽略優(yōu)先量詞,當(dāng)我們使用的44\d{3}不能匹配的時(shí)候,強(qiáng)制要求該表達(dá)式進(jìn)行匹配,這樣就可以進(jìn)行一次44開頭的5位數(shù)匹配,失敗,則直接跳過(匹配)不需要的5位數(shù),再次進(jìn)行嘗試,

總結(jié)

  • 上面的辦法就可以保證每次在需要匹配我們需要的數(shù)據(jù)的時(shí)候,位置是從5的倍數(shù)的位置開始匹配的,因?yàn)槟鼙WC總是能夠匹配,

匹配失敗時(shí)候仍然會(huì)出現(xiàn)數(shù)據(jù)的不協(xié)調(diào)性

  • 當(dāng)最后不存在任何以5的倍數(shù)位置開始的44開頭的5位數(shù)的ZIP Codes時(shí)(但存在其他的ZIP Codes),這個(gè)時(shí)候會(huì)整體匹配失敗,接下里,數(shù)據(jù)的不協(xié)調(diào)性問題又出現(xiàn)了,
  • 接下來由于傳動(dòng)裝置的驅(qū)動(dòng),強(qiáng)制在下一個(gè)位置進(jìn)行嘗試匹配,這就導(dǎo)致在不是5的倍數(shù)的位置上進(jìn)行匹配,是沒有意義的,
  • 所以此時(shí)的急救措施可能會(huì)對(duì)我們要匹配數(shù)據(jù)的表達(dá)式使用可選的匹配——(44\d{3})?
  • 但是這也確實(shí)能夠解決這個(gè)問題,除了第三個(gè)表達(dá)式不可以,因?yàn)樗麑⒖偸悄軌虺晒Γ赡軙?huì)匹配0長度文本,仍然導(dǎo)致傳動(dòng)裝置的驅(qū)動(dòng),另外兩個(gè)的表達(dá)式都是匹配優(yōu)先的,當(dāng)最后匹配到文本結(jié)束時(shí),嘗試(44\d{3})?,其只能夠成功,所以也就不存在失配導(dǎo)致的數(shù)據(jù)不協(xié)調(diào)性了。

優(yōu)缺點(diǎn)

  • 即使內(nèi)容中不存在任何我們需要的44開頭的5位數(shù)ZIP Codes,但它也總是能夠匹配成功,
  • 但是卻具有較高的匹配速度,因?yàn)椴恍枰厮荩ヅ溥^程中也不會(huì)有傳動(dòng)裝置的驅(qū)動(dòng)

推薦解決方法

  • 更加通用的辦法是使用\G

正確表達(dá)式正確匹配一個(gè)字符串

  • "(\\.|[^"\\\n])*+"
    該表達(dá)式使用占有優(yōu)先量詞純粹是為了提高報(bào)告匹配失敗的速度
  • "(\\.|[^"\n])*+"
    該表達(dá)式必須使用占有優(yōu)先量詞,防止回溯使得第二個(gè)分支匹配\

關(guān)于正則引擎

  • NFA支持一些DFA不支持的功能
  1. 捕獲型括號(hào)
  2. 反向引用(是因?yàn)椴恢С?code>1)
  3. 忽略優(yōu)先量詞(因?yàn)?code>DFA盡量保證匹配當(dāng)前位置最長的文本,所以沒有意義)
  4. 所以也不會(huì)支持占有優(yōu)先量詞,和固化分組,和3的道理一樣
  5. 不支持環(huán)視

  • 但是DFA具有匹配效率很快,穩(wěn)定,總是能得到確定的結(jié)果(匹配最左最長的文本),但其在編譯階段會(huì)花費(fèi)較長的時(shí)間和內(nèi)存
  • 傳統(tǒng)型的NFA是控制能力最強(qiáng)的正則引擎,因此使用者可以使用該引擎的表達(dá)式主導(dǎo)的性質(zhì)來精確控制匹配過程。

傳統(tǒng)型NFA的多選分支

  • 它既不是匹配優(yōu)先的也不是忽略匹配優(yōu)先的,而是按照表達(dá)式在多選分支的順序逐個(gè)嘗試,當(dāng)當(dāng)前的表達(dá)式匹配失敗后,將嘗試下一個(gè)表達(dá)式,即為每個(gè)表達(dá)式匹配開始時(shí)候都保存一個(gè)備用狀態(tài),
  • 正是因?yàn)槿绱耍匀绻麄溆玫谋磉_(dá)式存在多個(gè)可以與原文本匹配的可能,一定要控制好順序,
  • 像這樣的多選分支沒有意義a((ab)\*|a\*)因?yàn)榈谝粋€(gè)子表達(dá)式(ab)*永遠(yuǎn)也不會(huì)匹配失敗,

一些匹配上的細(xì)節(jié)

  • 關(guān)于捕獲型括號(hào)
    ((regex)?)在這個(gè)表達(dá)式中存在兩個(gè)group,其中group1group2都可能成功捕獲到regex匹配的內(nèi)容,但是group1還可能捕獲到長度為0的字符串,但此時(shí),group2沒有被應(yīng)用,其值為NULL

肯定環(huán)視模擬固化分組

當(dāng)環(huán)視成功以后,其中的備用狀態(tài)將會(huì)被丟棄,所以可以使用回溯引用來捕獲剛剛環(huán)視的內(nèi)容如(?=(regex))\1,這個(gè)時(shí)候\1就是一段固定的文本值了,在對(duì)文本值\1進(jìn)行匹配的過程中顯然不會(huì)保存任何備用狀態(tài)。所以使用\1的匹配達(dá)到了一個(gè)固化分組的匹配效果

  • (?>regex)可以使用(?=(regex))\1來模擬,但通常固化分組的效率要更高些,因?yàn)榄h(huán)視的嘗試匹配后,接下來\1還會(huì)在重復(fù)進(jìn)行一次匹配,只不過這次將會(huì)消費(fèi)文本.

關(guān)于regex測(cè)試器

  • javaintellijregex都是采用當(dāng)前匹配的開始位置
  • regexr.comregex采用之前匹配的結(jié)束位置

關(guān)于NFADFA

  • NFA 表達(dá)式主導(dǎo)
  • DFA 文本主導(dǎo)
  • NFA支持忽略優(yōu)先量詞,DFA不支持,
  • 對(duì)于哪個(gè)分支應(yīng)答首先選擇?
    優(yōu)先量詞將采取進(jìn)行嘗試,而忽略優(yōu)先量詞采取跳過嘗試
  • 備用狀態(tài),回溯進(jìn)行時(shí),應(yīng)該選取哪個(gè)保存的狀態(tài)?
    當(dāng)本地失敗時(shí)將選擇最近保存的狀態(tài),使用的原則是LIFO(后進(jìn)先出,類似棧)

簡單的判斷正則引擎

  • 首先如果該引擎支持忽略優(yōu)先量詞,那么基本就能確定這是traditional nfa引擎了,因?yàn)?strong>忽略優(yōu)先量詞在dfa中不支持,且在POSIX nfa引擎中也沒有意義(我的猜測(cè)是這這個(gè)引擎的標(biāo)準(zhǔn)量詞可能默認(rèn)是貪婪型的),為了測(cè)試這一點(diǎn)可以使用模式nfa|nfa not匹配nfa not如果成功匹配的只是nfa,那么則能確定這是traditional nfa引擎,否則nfa not都能匹配,那么只可能是POSIX nfadfa引擎了
  • 如果之前的判斷排除它是traditional nfa引擎的可能,那么接下來要判斷它是POSIX nfa還是dfa引擎,dfa引擎是不支持捕獲性括號(hào),所以自然也不支持回溯引用,但是一些混合使用兩種引擎的系統(tǒng),當(dāng)沒有使用捕獲型括號(hào),那么將使用dfa引擎
  • 所以單純的通過其是否支持某些特性來判斷一個(gè)引擎將過于草率,其實(shí)可以通過下面的這個(gè)測(cè)試?yán)蛹纯膳袛喑鍪?code>POSIX nfa還是dfa引擎

使用模式:
X(.+)+X
匹配文本:
XX-----------------------------------------------------------------------

如果匹配要花費(fèi)很長的時(shí)間,那就是

之前匹配的結(jié)束位置,還是當(dāng)前匹配的開始位置

在對(duì)一個(gè)文本進(jìn)行多次匹配時(shí),如果之前匹配的文本長度大于0,則下次匹配的時(shí)候?qū)⑹褂弥捌ヅ涞慕Y(jié)束位置,否則傳動(dòng)裝置將強(qiáng)行前進(jìn)到下一個(gè)字符,就使用當(dāng)前匹配的開始位置

匹配模式(?mode)和作用域

模式
  • i 忽略大小寫匹配
  • x 寬松排列和注釋模式
  • s 點(diǎn)號(hào)通配模式
  • m 增強(qiáng)的行錨點(diǎn)模式
作用域
  • (otherRegex)(?mode)(targetRegex)(?-mode)(otherRegex)
    在上面的例子中(?mode)會(huì)啟用該模式并作用于targetRegex直到(?-mode)將停用此功能
  • (otherRegex)(?:(?mode)targetRegex)(otherRegex)
    在上面的例子中(?mode)會(huì)啟用該模式并作用于targetRegex直到閉括號(hào)的結(jié)束
  • (otherRegex)(?mode:targetRegex)(otherRegex)
    上面表達(dá)式的一種簡寫方式,表示模式的修飾范圍只在括號(hào)內(nèi)有效

(page: 135)

Java regex 字符組集合操作

假如要匹配除元音字母的其他任意英語小寫字母,則可寫為
[[a-z]&&[^aeiou]]
[...]&&[^....]來表示-的集合操作

同時(shí)也可以使用環(huán)視來模擬此功能:
  • [a-z](?<![aeiou])
  • [a-z](?<=[^aeiou])

上面的意思是先匹配一個(gè)字母,然后再確保匹配好的字符不能是元音字母


  • (?![aeiou])[a-z]
  • (?=[^aeiou])[a-z]

上面的意思是先把光標(biāo)定位到除元音字母以外的任意字符的左邊,然后匹配小寫字母

Java使用regex的/x模式,內(nèi)嵌注釋

String regex = "(?x)M" +
                "#This is an Note\n" +
                "A#666\n";
  • 實(shí)際上得到的正則表達(dá)式是:(?x)MA
  • 也即#Ln包括它們之間的字符都將被視為注釋

Java字符串文本與正則表達(dá)式的關(guān)系

regex = "(?x)S S\t\\t\n\\n"

status value
Java src text (?x)S S\t\\t\n\\n
Java compiled text (?x)S STab\tLn\n
regex (?x)SS\t\n

因?yàn)?code>(/x)的模式的影響,忽略所有的空白字符作為最后的regex,這可能會(huì)讓人有點(diǎn)疑惑,那為什么\t\n依然存在,這是因?yàn)?code>\t和\n分別是兩個(gè)字符\, t\, n字符的組合,這些字符本身都不是空白字符,只是regex用來匹配的時(shí)候會(huì)將\t\n視為元序列字符,分別匹配制表符和換行符

環(huán)視

  • 肯定順序環(huán)視(?=)
  • 肯定逆序環(huán)視(?<=)
  • 否定順序環(huán)視(?!)
  • 否定逆序環(huán)視(?<!)
  • 利用環(huán)視可以模擬一些流派上不支持的正則表達(dá)式符號(hào),
metacharacter lookaround
</ (?<=\W)(?=\w)
/> (?<!\W)(?!\w)
\b </|/>, (?<=\W)(?=\w)|(?<=\w)(?=\W)
\B (?<=\W)(?=\W)|(?<=\w)(?=\w)

但元字符卻具有更高的效率

451545類似的數(shù)值從右往左每3個(gè)數(shù)字添加一個(gè)逗號(hào),且最右邊不添加

  • 真正解決這個(gè)問題應(yīng)該使用表達(dá)式
    (?<=\d)(?=(?:\d{3})+\b)只能使用環(huán)視,因?yàn)樵谝粋€(gè)數(shù)值中要添加多次逗號(hào),
    而通常的做法是只要每次匹配到3個(gè)數(shù)字且它們前面還有數(shù)字的話,它們的前面就應(yīng)該添加一個(gè)逗號(hào),前面有逗號(hào)的話,只需要逆序環(huán)視(?<=\d)即可,但是考慮到匹配后面3的整數(shù)倍的數(shù)值,只能使用順序環(huán)視,因?yàn)楹唵问褂?\d{3})+\b將會(huì)消費(fèi)后面的所有文本,

  • 所以只能添加一個(gè)逗號(hào),而且還會(huì)出錯(cuò),
    應(yīng)該使用順序環(huán)視(?=(\d{3})+\b)可以重復(fù)檢查后面的文本,依次找出所有需要添加逗號(hào)的位置

  • 在這樣之所以使用(?:...)非捕獲型的括號(hào)是因?yàn)榉凑@個(gè)regex的該子表達(dá)式捕獲到的$1不會(huì)被使用,而且它效率更高,因?yàn)橐娌恍枰洃洸东@的文本。但是卻丟失了一定的可讀性

Intellij IDEAregex的特點(diǎn)

  • 對(duì)于匹配同一個(gè)位置,常常可被匹配到兩次,這很可能是因?yàn)樗雌ヅ湟粋€(gè)字符結(jié)束位置,也匹配一個(gè)字符的開始位置,所以同-個(gè)位置可能被視為2個(gè)位置----開始和結(jié)束

[ \t]*( *|\t*)的區(qū)別

  • ( *|\t*)只能匹配sapce\t的連續(xù)序列,而不能匹配它們的混合序列
  • [ \t]*不但能匹配包括( *|\t*)能夠匹配的內(nèi)容,還能匹配sapce\t的混合序列
  • 實(shí)際上[ \t]*( |\t)*邏輯上是等價(jià)的,但是字符組的效率卻更高一些

非捕獲型括號(hào)(?:...)

  • (?:...)只分組不捕獲
  • (...)即分組又捕獲

如表達(dá)式([+-]?\d+(\.\d*)?)\s*([CF])([+-]?\d+(?:\.\d*)?)\s*([CF])

RegEx ([+-]?\d+(\.\d*)?)\s*([CF]) ([+-]?\d+(?:\.\d*)?)\s*([CF])
\1 ([+-]?\d+(\.\d*)?) ([+-]?\d+(?:\.\d*)?)
\2 (\.\d*) ([CF])
\3 ([CF]) NULL

書中可能的錯(cuò)誤列表

  • 但我們知道 First|1st(fir|1)st表示的是同一個(gè)意思 (page: 13)
  • \w 應(yīng)該還能匹配_ (page: 49)
  • E-mail Message范本倒數(shù)第三行可能在一些英文單詞上少了一些空格 (page: 54)
  • 下面的程序段可能存在過多的}字符 (page: 57)
  • 在a標(biāo)簽的href引用的鏈接應(yīng)該用雙引號(hào)包圍 (page: 74)
  • 關(guān)于字符串文字的若干例子, 字符串文本[\t\x2A]/x模式下只能匹配* (page: 102)
  • 十進(jìn)制編碼015,應(yīng)該是八進(jìn)制編碼才對(duì) (page: 115)
  • [^LMNOP]通常等價(jià)于[\x00-KQ-\xFF]而不是[\x00-kQ-\xFF] (page: 119)
  • 匹配HTML Tag,使用的表達(dá)式是<("[^"]"|'[^']'|[^">'])*+>,這樣會(huì)匹配到<>,所以應(yīng)該使用<("[^"]"|'[^']'|[^">'])++> (page: 200)

疑問列表

  1. 表達(dá)式(a)?b\1還能匹配除文本aba以外的其他文本嗎?(待研究)

API

  • 元字符 (page: 32)
  • 一些語法 (page: 114)
  • 字母表 (page: 123)

子表達(dá)式定義

子表達(dá)式是只正則表達(dá)式中的一部分,通常是括號(hào)內(nèi)的表達(dá)式
^(Subject|Date):中,(Subject|Date)通常被視為一個(gè)子表達(dá)式
其中SubjectDate也算是子表達(dá)式。而且,嚴(yán)格來講
S u b j …… 這些都算是子表達(dá)式。

匹配位置的元字符\B\b\<\>

  1. 它們都匹配一個(gè)位置
  2. 它們都是元字符序列
  • \B匹配的位置在\W\W\w\w之間
  • \b匹配的位置在\W\w\w\W之間
  • \<匹配的位置在\W\w之間
  • \>匹配的位置在\w\W之間

使用regex檢索文本的精確度

取決于我們對(duì)需要檢索的文本的了解程度。
舉個(gè)極端的例子,要匹配一個(gè)文件內(nèi)的所有數(shù)字,顯然可以使用
\d,但是如果我們清楚的明白我們的文件內(nèi)的內(nèi)容都是純數(shù)字的話,
可以簡單的使用.

關(guān)于grep

grep會(huì)在檢查regex之前把換行符刪除掉,
然后再用regex與每行刪除完換行符剩下的內(nèi)容進(jìn)行匹配

關(guān)于在字符組中的元字符^

[^……]將會(huì)匹配未被列出的任意字符,
而且只有當(dāng)^出現(xiàn)在[的最左邊時(shí),它才是一個(gè)元字符
[^^]第二個(gè)^就只是普通字符,這個(gè)模式的含義是它將匹配出除^字符以外的任意字符

關(guān)于元字符^$

  • ^匹配行開頭
  • $匹配行結(jié)尾
更具體的說明

但如果使用了增強(qiáng)的行錨點(diǎn)模式

  • 那么^不但能狗匹配字符串開頭還能匹配每個(gè)換行符后面的位置(但不能匹配字符串結(jié)束位置)
  • 同樣$還能匹配每個(gè)換行符的開始位置(左邊)
  • 所以使用\A,可以總是匹配字符串的開頭
  • 使用\Z\z,可以總是匹配字符串的結(jié)束

關(guān)于在字符組中的連字符-

  • [0-9A-Z_!.?]能夠匹配一個(gè)數(shù)字,大寫字母,下劃線,驚嘆號(hào),點(diǎn)號(hào),或者是問號(hào)。
  • 只有在字符組內(nèi)部,連字符才有可能是元字符----否則他就只能匹配普通的連字符號(hào),
  • 當(dāng)不能形成一個(gè)范圍的時(shí)候,它就是一個(gè)普通的連字符號(hào)
  • [a-z-]第二個(gè)連字符就將被解釋為一個(gè)普通的連字符號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 揭開正則表達(dá)式的神秘面紗(轉(zhuǎn)) 關(guān)閉高亮 [原創(chuàng)文章,轉(zhuǎn)載請(qǐng)保留或注明出處:http://www.regexlab...
    螃蟹六步郎閱讀 334評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評(píng)論 19 139
  • 轉(zhuǎn)自: JS正則表達(dá)式一條龍講解,從原理和語法到JS正則、ES6正則擴(kuò)展,最后再到正則實(shí)踐思路 溫馨提示:文章很長...
    前端渣渣閱讀 1,842評(píng)論 1 32
  • 本文譯自 制作正則引擎的作者 Jan Goyvaerts 為工具 RegexBuddy 寫的教程版權(quán)歸原作者所有注...
    極客圈閱讀 3,322評(píng)論 0 25
  • 01 都在講誰誰誰情商高的不行不行的,誰誰誰情商不叫低,簡直就是沒有情商……等等等等,每天聽的太多了,的確,話是這...
    你是紅領(lǐng)巾嗎閱讀 231評(píng)論 0 0