分组
撰写时间:2024-03-01
修订时间:2024-03-06
概述
为了匹配,我们需要描述特定字符的独特的特征。例如,要匹配HTML的各个标签,我们就得先描述这些标签的特征,才能得到整个标签的内容。而得到匹配结果后,我们可以通过分组,将匹配结果中的标签属性名、属性值、标签内容再次分类提取出来。
(x) : 捕获组
用(x)
来捕获x
。
one
two
`; let re = /(\w+)
/g;上面的结果中,捕获结果用绿色加亮显示。
(?:x) : 非捕获的分组
用(?:x)
来对x
分组,但不捕获。先看下面的捕获组例子。
上面,不管acceptable
的前面有没有un
,我们都希望予以匹配。因为这里un
作为一个整体,要么全都没有,要么就作为整体出现1次,因此我们在其前面加上了一个带括号的0或1的量词(un)?
。
从结果中,我们看到了有亮绿色,说明正则表达式引擎不仅将其分组,同时也捕获下来了。如果我们只保留其分组功能,但不想到其被捕获而浪费内存,则可使用非捕获的分组表达式(?:x)
。
只需在分组内部的最前面加上?:
,即可将该捕获组改为非捕获的分组。上面依然匹配了unacceptable
,但亮绿色消失了,说明正则表达式引擎这回并未将其捕获。
(?<Name>x) : 命名捕获组
用(x)
来捕获x
。
上面,属性名id将被捕获下来,并以attrName的名称存储到匹配结果的groups属性中。我们可以这样查看其结果:
显示:
可见,使用命名捕获组可帮我们清晰地辨识所捕获的内容。
pattern已经开始变得有些晃眼了。这是HTML的结构导致的结果。实际上,HTML的结构比我们所想像得到的还要复杂。我们会专述如何精细地匹配HTML。
\n : 反向引用第n个捕获组
创建捕获组后,可用\n
来引用之前的第n个捕获组。
one
在本例的捕获组中,使用<(\w+)>
来匹配1或多个字母,这样,便可同时匹配<p>
及<div>
。
但对于后面结尾部分的标签,如果只是简单地使用</(\w+)>
则会有问题,因为它能匹配到:
这样的错误结果。而后面的标签名必须与标签名完全一致。反向引用(back reference)则很好地解决了此问题。我们将各个标签名都捕获进第1个捕获组后,后面的部分要引用该标签名,只需使用\1
即可。这样,如果前面匹配到<p>
,则连同后面部分就会匹配到:
而如果前面的捕获组匹配到<div>
,则会匹配:
反向引用由此是个非常灵活、实用的功能。
\k<Name> : 反向引用命名捕获组
创建命名捕获组后,可用\k<Name>
来引用之前的该名称的捕获组。
one
与上一节的反向引用捕获组相类似,反向引用命名捕获组可引用前面的命名捕获组,从而达到灵活、精准又好记的效果。
本章小结
捕获组具有两个作用:一是分组,二是捕获。
通过分组,我们可为组内的多个成员同时设定量词等。而如果不想捕获,可使用非捕获的分组。
在String的replace方法中,我们可利用所捕获的结果来达到灵活替换的功能。而反向引用的功能,则是进一步优化了匹配过程,既提高了匹配的效率,同时也扩大了匹配的应用范围。
至此,我们已经全面涵盖了正则表达式的匹配功能这个最重要的核心部分。正则表达式的学习内容不算多,也不难理解,但就是经常出现费了老大的劲、却不能精准匹配的情况。
而要有效解决此问题,一是多练习,二是非主题的细节需要进一步的了解,如转义的问题等等。后面几章会围绕这些问题进行专题阐述。