- 論壇徽章:
- 0
|
在搞清楚所述及的問題之前
首先明確一下什么是匹配
匹配可以從兩個方面來理解
1 一個正則表達(dá)式和一個字符串是否匹配
在perl中 =~ 代表捆綁 也就是讓正則表達(dá)式去匹配指定的字符串
如果如果用匹配的符號形式來表現(xiàn) 對于 /regular/ =~ "string" 如果返回值為真 則說/regular/ 匹配了"string"
2 一個正則表達(dá)式不只可以匹配一個字符串
例如 /a*b/ 不僅可以匹配aaaab 還可以匹配aaaaaab b 等
這里所謂的“匹配”也是指 /a*b/ =~ aaaab /a*b/ =~ b 返回值都是真
下面說說依次匹配
首先的一個問題是一個正則表達(dá)式的工作過程
舉個例子
- $data is 192.168.0.1
- $data =~ /([0-9]*\.)([0-9]*.)([0-9]*\.)([0-9])/;
- $1 is 192.
- $2 is 168.
- $3 is 0.
- $4 is 1
- 這里
- /([0-9]*\.)([0-9]*\.)([0-9]*\.)([0-9])/ 匹配了192.168.0.1
- 同時在這個較長的正則表達(dá)式子是由幾個短的正則表達(dá)式組成的,這些短的在()中的正則表達(dá)式稱為模式,大家對$1,$2,$3,$4的值的輸出都非常理解
復(fù)制代碼
下面再舉一個例子
- $data =~ /([0-9]*\.)([0-9]*\.)*([0-9])/;
- $1 is 192.
- $2 is 0.
- $3 is 1
復(fù)制代碼
這里有觀點解釋到這里([0-9]*\.) ([0-9]*\.) *([0-9]) 紅色部分"依次匹配" 了168. 0. 所以是0.
這并不是很好理解
有證:
[quote]原帖由 "3x3eyes"]....匹配.168都還好理解所謂的依次匹配是什么意思,請各位幫忙[/quote 發(fā)表:
問題的關(guān)鍵是為什么這里的紅色部分會去依次匹配168. 0.呢?regular 有這種依次匹配的機制嗎 它在什么情況下會這樣做 什么情況下不會這么做呢
下面我們通過一個例子來驗證regular 會不會有這種依次匹配的機制
- $data =~ /([0-9]*\.)([0-9]*\.)([0-9])/;
- $1 is 192.
- $2 is 168.
- $3 is 0
復(fù)制代碼
這里紅色部分并沒有去依次匹配168. 0. 而是直接匹配了168.
為什么呢 看來 問題出現(xiàn)在* 上面
也就是當(dāng)正則表達(dá)式是 $data =~ /([0-9]*\.)([0-9]*\.)*([0-9])/; 的時候 紅色部分依次匹配了168. 0. 并最終把最后匹配的0.存到了分組2中
當(dāng)正則表達(dá)式是 $data =~ /([0-9]*\.)([0-9]*\.)([0-9])/; 的時候 紅色部分就不再依次匹配了?? 它就匹配168. 并把168存在分組2中 這是什么道理?
正則表達(dá)式有一個引擎 引擎的工作原理細(xì)節(jié)沒有找到相應(yīng)文檔 但是對于這種情況 可以試著解釋為
- 對于 $data =~ /([0-9]*\.)([0-9]*\.)([0-9])/;
- 這時候?qū)τ谀J? 模式2 模式3 他們沒有機會選擇 分別將各自匹配的 192. 168. 0 存在正則表達(dá)式的記憶體 \1 \2 \3中
- 而對于 $data =~ /([0-9]*\.)([0-9]*\.)*([0-9])/;
- 對于模式1 從左到右搜索$data 匹配了192. 把它存在了記憶體 \1中
- 對于模式2 從左到右搜索剩下的$data 部分 匹配了 168. 并把它存在了記憶體\2中
- 下面到了* 這里*代表 前面模式的0次或多次出現(xiàn) 雖然在功能上對于這個例子它等于([0-9]*\.)([0-9]*\.)([0-9]*\.)([0-9])/, 但是它并不等價于正則表達(dá)式/([0-9]*\.)([0-9]*\.)([0-9]*\.)([0-9])/ 。這時候仍然是模式2 去從左到右搜索$data剩余的字符串0.1 結(jié)果匹配了0. 由于仍然是模式2去匹配,所以0. 仍然存在記憶體\2中,沖掉了原來存在記憶體\2中的內(nèi)容 下面([0-9]) 匹配了1 并把它存在了記憶體\3中。
復(fù)制代碼
看到這里,可以試著總結(jié)出正則表達(dá)式的引擎搜索機制:
- 1 如果在正則表達(dá)式中有模式 ,那么每個模式從左到右搜索要匹配的字符串,如果匹配成功,則把匹配的字符串存到相對應(yīng)的記憶體中。
- 2 如果正則表達(dá)式中有下一個模式,那么這個模式將繼續(xù)從左到右搜索沒有被匹配的字符串 ,重復(fù)前面的步驟1的過程,匹配成功則立即停止,并把匹配的字符串存到相應(yīng)的記憶體中。
- 3 如果在2中的模式后面出現(xiàn)了數(shù)量符* + ? ,形如:(模式2)*,則匹配過程變?yōu)椋耗J?仍然按照步驟1的過程匹配,匹配成功則停止。但是由于這時候在模式2后面出現(xiàn)了數(shù)量符 * ,則仍然由模式2去匹配字符串中沒有被匹配的的部分,如果這時候出現(xiàn)了可以匹配多個字符串的情況,那么作后一次匹配成功的字符串被存放到了模式2對應(yīng)的記憶體中(注意:中間匹配成功的并不是沒有存,而是被后面匹配成功的覆蓋了)。
復(fù)制代碼
說到這里仿佛一切問題都得到了很好的解釋
可是請看下面的例子
- $data = 192.168.0.1
- $data =~ /([0-9]*\.)([0-9]*\.)*([0-9]*\.)([0-9]*.)([0-9])/
- 按照上面的結(jié)論,大家不妨猜測一下\2的內(nèi)容 ,也就是記憶體2中的值是什么
- 在沒有看到答案之前,也許會有人猜測是0. 或者168.。
- 但是這里 \2的值是空值,*在這里是“0個”。
復(fù)制代碼
由此可以得到:正則表達(dá)式并不是按照模式按照從左到右搜索,"一個正則表達(dá)式" 就是一段程序,一個正則表達(dá)式的匹配引擎機制應(yīng)該是:盡量多的精確的去匹配目標(biāo)字符串,至于它采取哪種策略實現(xiàn)這一過程,這也是在此拋磚引玉的目的所在。 |
|