这篇文章主要介绍了 javascript 正则表达式分组、断言详解的相关资料,需要的朋友可以参考下
javascript 正则表达式分组、断言详解
提示:阅读本文需要有一定的正则表达式基础。
正则表达式中的断言,作为高级应用出现,倒不是因为它有多难,而是概念比较抽象,不容易理解而已,今天就让小菜通俗的讲解一下。
如果不用断言,以往用过的那些表达式,仅仅能获取到有规律的字符串,而不能获取无规律的字符串。
举个例子,比如html源码中有
想解决以上问题,就要用到断言知识。
在讲断言之前,读者应该先了解分组,这有助于理解断言。
分组在正则中用()表示,根据小菜理解,分组的作用有两个:
n 将某些规律看成是一组,然后进行组级别的重复,可以得到意想不到的效果。
n 分组之后,可以通过后向引用简化表达式。
先来看第一个作用,对于IP地址的匹配,简单的可以写为如下形式:
\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}
但仔细观察,我们可以发现一定的规律,可以把.\d{1,3}看成一个整体,也就是把他们看成一组,再把这个组重复3次即可。表达式如下:
\d{1,3}(.\d{1,3}){3}
这样一看,就比较简洁了。
再来看第二个作用,就拿匹配
<title>.*</title>
可以看出,上边表达式中有两个title,完全一样,其实可以通过分组简写。表达式如下:
<(title)>.*</\1>
这个例子实际上就是反向引用的实际应用。对于分组而言,整个表达式永远算作第0组,在本例中,第0组是<(title)>.*\1>,然后从左到右,依次为分组编号,因此,(title)是第1组。
用\1这种语法,可以引用某组的文本内容,\1当然就是引用第1组的文本内容了,这样一来,就可以简化正则表达式,只写一次title,把它放在组里,然后在后边引用即可。
以此为启发,我们可不可以简化刚刚的IP地址正则表达式呢?原来的表达式为\d{1,3}(.\d{1,3}){3},里边的\d{1,3}重复了两次,如果利用后向引用简化,表达式如下:
(\d{1,3})(.\1){3}
简单的解释下,把\d{1,3}放在一组里,表示为(\d{1,3}),它是第1组,(.\1)是第2组,在第2组里通过\1语法,后向引用了第1组的文本内容。
经过实际测试,会发现这样写是错误的,为什么呢?
小菜一直在强调,后向引用,引用的仅仅是文本内容,而不是正则表达式!
也就是说,组中的内容一旦匹配成功,后向引用,引用的就是匹配成功后的内容,引用的是结果,而不是表达式。
因此,(\d{1,3})(.\1){3}这个表达式实际上匹配的是四个数都相同的IP地址,比如:123.123.123.123。
至此,读者已经掌握了传说中的后向引用,就这么简单。
接下来说说什么是断言。
所謂斷言,就是指明某個字串前邊或後邊,將會出現滿足某種規律的字串。
就拿文章開篇的例子來說,我們想要的是xxx,它沒有規律,但是它前邊肯定會有
想指定xxx前一定會出現
一定會出現
兩個加在一起,就是(?<=
這樣就能搭配xxx。
相信讀者看到這,已經蒙了,不用急,待小菜慢慢講來。
其實掌握了規律,就很簡單了,無論是先行還是後發,都是相對於xxx而言的,也就是相對於目標字串而言。
假如目標字串後邊有條件,可以理解為目標字串在前,就用先行斷言,放在目標字串之後。
假如目標字串前邊有條件,可以理解為目標字串在後,就用後發斷言,放在目標字串之前。
假如指定滿足某一條件,為正。
假如指定不符合某個條件,為負。
斷言只是條件,幫你找出真正需要的字串,本身並不會符合!
(?=X ) |
#零寬度正先行斷言。僅當子表達式 X 在 此位置的右側匹配時才繼續匹配。例如,/w+(?=/d) 與後跟數字的單字匹配,而不與該數字匹配。此構造不會回溯。 |
(?!X) |
#零寬度負先行斷言。僅當子表達式 X 不在 此位置的右側匹配時才繼續匹配。例如,例如,/w+(?!/d) 與後面不跟數字的單字匹配,而不與該數字匹配 。 |
(?<=X) |
#零寬度正後發斷言。僅當子表達式 X 在 此位置的左側匹配時才繼續匹配。例如,(?<=19)99 與跟在 19 後面的 99 的實例相符。此構造不會回溯。 |
(? |
#零寬度負後發斷言。僅當子表達式 X 不在此位置的左側匹配時才繼續匹配。例如,(? |
從斷言的表達形式可以看出,它用的就是分組符號,只不過開頭都加了一個問號,這個問號就是在說這是一個非捕獲組,這個組沒有編號,不能用來後向引用,只能當做斷言。
以上是javascript正規表示式的分組以及斷言的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!