構(gòu)建掃描器程序的兩個(gè)重要方法
boolean hitEnd()
- 返回true,說(shuō)明結(jié)尾有更多的字符可能會(huì)改變本次的匹配結(jié)果(匹配成功變成失敗,失敗變成成功,或者匹配內(nèi)容發(fā)生改變)
- 返回false,說(shuō)明結(jié)尾有更多的字符不會(huì)改變本次的匹配結(jié)果
boolean requireEnd()
只有匹配成功該方法的返回值才有意義
- 返回true,說(shuō)明結(jié)尾有更多的字符可能會(huì)使得本次匹配失敗
- 返回false,說(shuō)明結(jié)尾有更多的字符不可能會(huì)使得本次匹配失敗,雖然可能會(huì)影響本次匹配的細(xì)節(jié),如匹配內(nèi)容發(fā)生改變
消除循環(huán)
(normal)*(special(normal)*)*
- 防止special部分造成的循環(huán)
special要能寫(xiě)成start(middle)*end
-
start-end和middle匹配的是無(wú)交集的兩部分 -
start和end是固化的文本,且start和end至少存在一部分,middle可不存在
- start(middle)* 是為了防止此模式匹配成功后,外層(...)*表達(dá)式還能夠繼續(xù)匹配,導(dǎo)致內(nèi)部和外部遞歸匹配一段文本,加上start,當(dāng)middle回溯文本時(shí),外部無(wú)法再匹配內(nèi)部交還的文本
- (middle)*end 是為了防止本次的匹配成功,如果本次不能匹配成功,那么外部也無(wú)法繼續(xù)應(yīng)用該表達(dá)式了,
- 防止normal部分造成的循環(huán)
- 把start看成special,middle看成normal,也就保證了(special(normal))不會(huì)造成無(wú)休止的匹配了,這是(start(middle)end)缺少end的一種形式
表達(dá)式的優(yōu)化
對(duì)于
(.*)(Suffix)這種以.*匹配優(yōu)先開(kāi)始的表達(dá)式通常可以在開(kāi)頭使用行開(kāi)頭錨點(diǎn)標(biāo)記^,
得到^(.*)(Suffix)這樣傳動(dòng)裝置只會(huì)在文本開(kāi)頭應(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ú)出來(lái)的思想,任何的優(yōu)化都是平等的,可能會(huì)因小失大, - 考慮到如果是位置匹配之類的可以放入到多選結(jié)構(gòu)內(nèi),但是如果尾部是
$,即行結(jié)尾標(biāo)記,則又將失去行結(jié)束錨點(diǎn)的優(yōu)化,也就是除了一些特殊的位置標(biāo)記,其他可以放入到多選結(jié)構(gòu)內(nèi),而一些單純的文本則不放入,將他們單獨(dú)分離出來(lái),可以得到文本中必須出現(xiàn)字符或字符串優(yōu)化.
\G使用之前匹配結(jié)束的位置
-
regex = "\\G(?:\\d{5})*?(44\\d{3})?"
如果使用該表達(dá)式匹配文本,一旦匹配的文本長(zhǎng)度為0,則將不會(huì)在進(jìn)行匹配,因?yàn)槭褂玫氖侵捌ヅ浣Y(jié)束的位置,傳動(dòng)裝置將不會(huì)驅(qū)動(dòng),使用引擎能知道下次在該處匹配也得到相同的結(jié)果,會(huì)無(wú)限循環(huán)
匹配44開(kāi)頭的5位數(shù)美國(guó)郵政編碼(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)行匹配的開(kāi)始,要保證左邊必須是5的倍數(shù)數(shù)字,所以使用正則表達(dá)式
(?<=^(?:\d{5})*)44\d{3},但這將使用逆序環(huán)視進(jìn)行掃描不定長(zhǎng)度的文本,一些正則引擎可能不支持, - 另一個(gè)辦法是保證數(shù)據(jù)的協(xié)調(diào)性,出現(xiàn)匹配錯(cuò)誤數(shù)據(jù)的原因主要是傳動(dòng)裝置的驅(qū)動(dòng),導(dǎo)致了數(shù)據(jù)的錯(cuò)位,實(shí)際上如果不是從5的倍數(shù)的位置開(kāi)始匹配,即使成功,也是沒(méi)有意義的數(shù)據(jù),所以可以使用一些表達(dá)式來(lái)跳過(guò)(匹配)不是44開(kāi)頭的的5位數(shù)
ZIP Codes,
3個(gè)辦法
-
[1235-9]\d{4}|\d[1235-9]\d{3}(如果開(kāi)頭44則失配) -
(?!44)\d{5}(如果開(kāi)頭不是44則匹配) -
(\d{5}*?)使用忽略優(yōu)先量詞,當(dāng)我們使用的44\d{3}不能匹配的時(shí)候,強(qiáng)制要求該表達(dá)式進(jìn)行匹配,這樣就可以進(jìn)行一次44開(kāi)頭的5位數(shù)匹配,失敗,則直接跳過(guò)(匹配)不需要的5位數(shù),再次進(jìn)行嘗試,
總結(jié)
- 上面的辦法就可以保證每次在需要匹配我們需要的數(shù)據(jù)的時(shí)候,位置是從5的倍數(shù)的位置開(kāi)始匹配的,因?yàn)槟鼙WC總是能夠匹配,
匹配失敗時(shí)候仍然會(huì)出現(xiàn)數(shù)據(jù)的不協(xié)調(diào)性
- 當(dāng)最后不存在任何以5的倍數(shù)位置開(kāi)始的44開(kāi)頭的5位數(shù)的
ZIP Codes時(shí)(但存在其他的ZIP Codes),這個(gè)時(shí)候會(huì)整體匹配失敗,接下里,數(shù)據(jù)的不協(xié)調(diào)性問(wèn)題又出現(xiàn)了, - 接下來(lái)由于傳動(dòng)裝置的驅(qū)動(dòng),強(qiáng)制在下一個(gè)位置進(jìn)行嘗試匹配,這就導(dǎo)致在不是5的倍數(shù)的位置上進(jìn)行匹配,是沒(méi)有意義的,
- 所以此時(shí)的急救措施可能會(huì)對(duì)我們要匹配數(shù)據(jù)的表達(dá)式使用可選的匹配——
(44\d{3})?, - 但是這也確實(shí)能夠解決這個(gè)問(wèn)題,除了第三個(gè)表達(dá)式不可以,因?yàn)樗麑⒖偸悄軌虺晒Γ赡軙?huì)匹配0長(zhǎng)度文本,仍然導(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開(kāi)頭的5位數(shù)
ZIP Codes,但它也總是能夠匹配成功, - 但是卻具有較高的匹配速度,因?yàn)椴恍枰厮?,匹配過(guò)程中也不會(huì)有傳動(dòng)裝置的驅(qū)動(dòng)
推薦解決方法
- 更加通用的辦法是使用\G
正確表達(dá)式正確匹配一個(gè)字符串
-
"(\\.|[^"\\\n])*+"
該表達(dá)式使用占有優(yōu)先量詞純粹是為了提高報(bào)告匹配失敗的速度 -
"(\\.|[^"\n])*+"
該表達(dá)式必須使用占有優(yōu)先量詞,防止回溯使得第二個(gè)分支匹配\
關(guān)于正則引擎
-
NFA支持一些DFA不支持的功能
- 捕獲型括號(hào)
- 反向引用(是因?yàn)椴恢С?code>1)
- 忽略優(yōu)先量詞(因?yàn)?code>DFA盡量保證匹配當(dāng)前位置最長(zhǎng)的文本,所以沒(méi)有意義)
- 所以也不會(huì)支持占有優(yōu)先量詞,和固化分組,和
3的道理一樣 - 不支持環(huán)視
- 但是
DFA具有匹配效率很快,穩(wěn)定,總是能得到確定的結(jié)果(匹配最左最長(zhǎng)的文本),但其在編譯階段會(huì)花費(fèi)較長(zhǎng)的時(shí)間和內(nèi)存 - 傳統(tǒng)型的
NFA是控制能力最強(qiáng)的正則引擎,因此使用者可以使用該引擎的表達(dá)式主導(dǎo)的性質(zhì)來(lái)精確控制匹配過(guò)程。
傳統(tǒng)型NFA的多選分支
- 它既不是匹配優(yōu)先的也不是忽略匹配優(yōu)先的,而是按照表達(dá)式在多選分支的順序逐個(gè)嘗試,當(dāng)當(dāng)前的表達(dá)式匹配失敗后,將嘗試下一個(gè)表達(dá)式,即為每個(gè)表達(dá)式匹配開(kāi)始時(shí)候都保存一個(gè)備用狀態(tài),
- 正是因?yàn)槿绱耍匀绻麄溆玫谋磉_(dá)式存在多個(gè)可以與原文本匹配的可能,一定要控制好順序,
- 像這樣的多選分支沒(méi)有意義
a((ab)\*|a\*)因?yàn)榈谝粋€(gè)子表達(dá)式(ab)*永遠(yuǎn)也不會(huì)匹配失敗,
一些匹配上的細(xì)節(jié)
- 關(guān)于捕獲型括號(hào)
((regex)?)在這個(gè)表達(dá)式中存在兩個(gè)group,其中group1和group2都可能成功捕獲到regex匹配的內(nèi)容,但是group1還可能捕獲到長(zhǎng)度為0的字符串,但此時(shí),group2沒(méi)有被應(yīng)用,其值為NULL
用肯定環(huán)視模擬固化分組
當(dāng)環(huán)視成功以后,其中的備用狀態(tài)將會(huì)被丟棄,所以可以使用回溯引用來(lái)捕獲剛剛環(huán)視的內(nèi)容如(?=(regex))\1,這個(gè)時(shí)候\1就是一段固定的文本值了,在對(duì)文本值\1進(jìn)行匹配的過(guò)程中顯然不會(huì)保存任何備用狀態(tài)。所以使用\1的匹配達(dá)到了一個(gè)固化分組的匹配效果
-
(?>regex)可以使用(?=(regex))\1來(lái)模擬,但通常固化分組的效率要更高些,因?yàn)榄h(huán)視的嘗試匹配后,接下來(lái)\1還會(huì)在重復(fù)進(jìn)行一次匹配,只不過(guò)這次將會(huì)消費(fèi)文本.
關(guān)于regex測(cè)試器
-
java和intellij的regex都是采用當(dāng)前匹配的開(kāi)始位置 -
regexr.com的regex采用之前匹配的結(jié)束位置
關(guān)于NFA和DFA
-
NFA表達(dá)式主導(dǎo) -
DFA文本主導(dǎo) -
NFA支持忽略優(yōu)先量詞,DFA不支持, - 對(duì)于哪個(gè)分支應(yīng)答首先選擇?
優(yōu)先量詞將采取進(jìn)行嘗試,而忽略優(yōu)先量詞采取跳過(guò)嘗試 - 備用狀態(tài),回溯進(jìn)行時(shí),應(yīng)該選取哪個(gè)保存的狀態(tài)?
當(dāng)本地失敗時(shí)將選擇最近保存的狀態(tài),使用的原則是LIFO(后進(jìn)先出,類似棧)
簡(jiǎn)單的判斷正則引擎
- 首先如果該引擎支持忽略優(yōu)先量詞,那么基本就能確定這是
traditional nfa引擎了,因?yàn)?strong>忽略優(yōu)先量詞在dfa中不支持,且在POSIX nfa引擎中也沒(méi)有意義(我的猜測(cè)是這這個(gè)引擎的標(biāo)準(zhǔn)量詞可能默認(rèn)是貪婪型的),為了測(cè)試這一點(diǎn)可以使用模式nfa|nfa not匹配nfa not如果成功匹配的只是nfa,那么則能確定這是traditional nfa引擎,否則nfa not都能匹配,那么只可能是POSIX nfa或dfa引擎了 - 如果之前的判斷排除它是
traditional nfa引擎的可能,那么接下來(lái)要判斷它是POSIX nfa還是dfa引擎,dfa引擎是不支持捕獲性括號(hào),所以自然也不支持回溯引用,但是一些混合使用兩種引擎的系統(tǒng),當(dāng)沒(méi)有使用捕獲型括號(hào),那么將使用dfa引擎 - 所以單純的通過(guò)其是否支持某些特性來(lái)判斷一個(gè)引擎將過(guò)于草率,其實(shí)可以通過(guò)下面的這個(gè)測(cè)試?yán)蛹纯膳袛喑鍪?code>POSIX nfa還是
dfa引擎
使用模式:
X(.+)+X
匹配文本:
XX-----------------------------------------------------------------------
如果匹配要花費(fèi)很長(zhǎng)的時(shí)間,那就是
之前匹配的結(jié)束位置,還是當(dāng)前匹配的開(kāi)始位置
在對(duì)一個(gè)文本進(jìn)行多次匹配時(shí),如果之前匹配的文本長(zhǎng)度大于0,則下次匹配的時(shí)候?qū)⑹褂弥捌ヅ涞慕Y(jié)束位置,否則傳動(dòng)裝置將強(qiáng)行前進(jìn)到下一個(gè)字符,就使用當(dāng)前匹配的開(kāi)始位置
匹配模式(?mode)和作用域
模式
-
i忽略大小寫(xiě)匹配 -
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á)式的一種簡(jiǎn)寫(xiě)方式,表示模式的修飾范圍只在括號(hào)內(nèi)有效
(page: 135)
Java regex 字符組集合操作
假如要匹配除元音字母的其他任意英語(yǔ)小寫(xiě)字母,則可寫(xiě)為
[[a-z]&&[^aeiou]]
[...]&&[^....]來(lái)表示-的集合操作
同時(shí)也可以使用環(huán)視來(lái)模擬此功能:
[a-z](?<![aeiou])[a-z](?<=[^aeiou])
上面的意思是先匹配一個(gè)字母,然后再確保匹配好的字符不能是元音字母
(?![aeiou])[a-z](?=[^aeiou])[a-z]
上面的意思是先把光標(biāo)定位到除元音字母以外的任意字符的左邊,然后匹配小寫(xiě)字母
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用來(lái)匹配的時(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è)問(wèn)題應(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)楹?jiǎ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 IDEA的regex的特點(diǎn)
- 對(duì)于匹配同一個(gè)位置,常??杀黄ヅ涞絻纱危@很可能是因?yàn)樗雌ヅ湟粋€(gè)字符結(jié)束位置,也匹配一個(gè)字符的開(kāi)始位置,所以同-個(gè)位置可能被視為2個(gè)位置----開(kāi)始和結(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 |
書(shū)中可能的錯(cuò)誤列表
- 但我們知道
First|1st與(fir|1)st表示的是同一個(gè)意思(page: 13) -
\w應(yīng)該還能匹配_(page: 49) - E-mail Message范本倒數(shù)第三行可能在一些英文單詞上少了一些空格
(page: 54) - 下面的程序段可能存在過(guò)多的
}字符(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)
疑問(wèn)列表
- 表達(dá)式
(a)?b\1還能匹配除文本aba以外的其他文本嗎?(待研究)
API
- 元字符
(page: 32) - 一些語(yǔ)法
(page: 114) - 字母表
(page: 123)
子表達(dá)式定義
子表達(dá)式是只正則表達(dá)式中的一部分,通常是括號(hào)內(nèi)的表達(dá)式
如^(Subject|Date):中,(Subject|Date)通常被視為一個(gè)子表達(dá)式
其中Subject和Date也算是子表達(dá)式。而且,嚴(yán)格來(lái)講
S u b j …… 這些都算是子表達(dá)式。
匹配位置的元字符\B,\b,\<,\>
- 它們都匹配一個(gè)位置
- 它們都是元字符序列
-
\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ù)字的話,
可以簡(jiǎn)單的使用.
關(guān)于grep
grep會(huì)在檢查regex之前把換行符刪除掉,
然后再用regex與每行刪除完換行符剩下的內(nèi)容進(jìn)行匹配
關(guān)于在字符組中的元字符^
[^……]將會(huì)匹配未被列出的任意字符,
而且只有當(dāng)^出現(xiàn)在[的最左邊時(shí),它才是一個(gè)元字符
[^^]第二個(gè)^就只是普通字符,這個(gè)模式的含義是它將匹配出除^字符以外的任意字符
關(guān)于元字符^和$
-
^匹配行開(kāi)頭 -
$匹配行結(jié)尾
更具體的說(shuō)明
但如果使用了增強(qiáng)的行錨點(diǎn)模式
- 那么
^不但能狗匹配字符串開(kāi)頭還能匹配每個(gè)換行符后面的位置(但不能匹配字符串結(jié)束位置) - 同樣
$還能匹配每個(gè)換行符的開(kāi)始位置(左邊) - 所以使用
\A,可以總是匹配字符串的開(kāi)頭 - 使用
\Z和\z,可以總是匹配字符串的結(jié)束
關(guān)于在字符組中的連字符-
-
[0-9A-Z_!.?]能夠匹配一個(gè)數(shù)字,大寫(xiě)字母,下劃線,驚嘆號(hào),點(diǎn)號(hào),或者是問(wèn)號(hào)。 - 只有在字符組內(nèi)部,連字符才有可能是元字符----否則他就只能匹配普通的連字符號(hào),
- 當(dāng)不能形成一個(gè)范圍的時(shí)候,它就是一個(gè)普通的連字符號(hào)
- 如
[a-z-]第二個(gè)連字符就將被解釋為一個(gè)普通的連字符號(hào)