php正则表达式中命名子组,【正则表达式系列】一些概念(字符组、捕获组、非捕获组)...

前言

本文介绍一些正则中的常用名词以及对应概念,譬如字符组,捕获组、非捕获组、反向引用、转义和\s \b等

大纲

字符组

捕获组

反向引用

非捕获组

.、\s和\S

\b

\转义

字符组

[]字符组表示在同一个位置可能出现的各种字符,也就是说它的匹配结果只能是一个字符,不能是多个

例如[hello]匹配的不是hello而是h或e或l或o

特点

结果只会匹配一个字符

内部特殊字符无需转义\ [ ] 除外

另外,^出现在最开始位置时需要转义

-前后构成区间范围时需要转义(推荐永远使用转义\-)

-表示连字符

^表示排除符

示例

特殊字符无需转义

[\^*\-+|(a)]

这个示例的含义是,匹配以下字符中的任意一个

^ * - + | ( a )

可以看到,这些特殊字符在字符组中仅仅就是字符本身

连字符的作用

[z-a]

匹配这个正则表达式会报错(Range out of order in character class)

原因是连字符后面的字符码要大于等于前面的字符码

var str = 'abc-';

var reg = /[a-z-]/g;

// 最后的连字符没有构成区间,所以仅仅表示 - 这个字符

str.match(reg); // ["a", "b", "c", "-"]

var str = "aAbc-";

var reg = /[A-a-z]/g;

// 通用,A-a 构成一个区间 之后的 -z 无法构成区间,于是它只能作为-字符本身

str.match(reg); // ["a", "A", "-"]

排除型

var str = '01ABabc-';

var reg = /[^a-z]/g;

// 匹配了除a-z范围外的任意字符

str.match(reg); // ["0", "1", "A", "B", "-"]

排除型字符组用法和普通的一样,但是唯一区别是

排除型代表符合条件的都不匹配(功能相反)

\b特殊情况

var str = 'ab\bd,cdef';

var reg = /[\b]/g;

var reg2 = /\bc/g;

var reg3 = /[\b]c/g;

str.match(reg); // [""] 匹配\b本身

str.match(reg2); // ["c"] 即匹配,号后面的c

str.match(reg3); // null 因为\b后面没有c

\b在字符组以外表示单词边界

在字符组内,表示退格符(\b)

捕获组

捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用

例如: /(a)(b)(c)/中的捕获组编号为

组0: abc

组1: a

组2: b

组3: c

其中,组0是正则表达式整体匹配结果,组1`2`3才是子表达式匹配结果

特点

子表达式捕获组编号从1开始,顺序从左到右(例如编号1是左侧第一个()包裹的子表达式的结果)

可以在正则表达式中对前面捕获的内容进行引用(反向引用)

也可以在程序中,对捕获组捕获的内容进行引用(比如replace中)

示例

子表达式捕获组编号从1开始,顺序从左到右

var str = "2017-07-29";

var reg = /(\d{4})-(\d{2})-(\d{2})/;

// 非全局模式有捕获组结果

str.match(reg); // ["2017-07-29", "2017", "07", "29", index: 0, input: "2017-07-29"]

上述匹配中,除了整个正则表达式的结果外,还有各个捕获组的结果,其中,子表达式的捕获组从编号1开始,如下

编号

捕获组

匹配内容

0

(d{4})-(d{2})-(d{2})

2017-07-29

1

d{4}

2017

2

d{2}

07

3

d{2}

29

JS程序内的引用

在replace中,JS通过$number引用捕获组内容

在外部匹配引用,JS通过RegExp.$number引用捕获组内容

var str = '

var reg = /]*>/g;

//

str = str.replace(reg, "");

可以看到,在去除div中的属性时,先是整个匹配,然后再把整个内容替换成,其中$1就是第一个捕获组结果div的引用

注,请不要引用$0,因为它不属于子表达式的捕获组,在replace中引用$0没有任何效果

var str = 'abcd0123ABCD';

var reg = /([a-z]+)(\d+)([A-Z]+)/g;

reg.test(str); // true

console.log(RegExp.$0); // undefined

console.log(RegExp.$1); // abcd

console.log(RegExp.$2); // 0123

console.log(RegExp.$3); // ABCD

注,同样$0的引用没有内容

反向引用

在正则表达式内部对捕获组进行引用称之为反向引用

var str = "boom==boom";

var reg = /(boom)==\1/;

str.match(reg); // ["boom==boom", "boom", index: 0, input: "boom==boom"]

可以看到,正则中\1的值就是捕获组1匹配到的结果boom

因此,这个表达式等价于(boom)==boom

示例

var str = '1234567899';

var str2 = '12345678999';

var reg = /^(?:([0-9])(?!\1{2})){1,}$/;

reg.test(str); // true

reg.test(str2); // false

上例中的效果是,匹配一个数字,但是数字中不允许连续出现3次以上的重复数字

用到反向引用可以很好的实现

非捕获组

上述可以看到()包括的内容默认匹配时都在捕获组中

但是有时候,因为特殊原因用到了(),但又没有引用它的必要,这时候就可以用非捕获组声明,防止它作为捕获组,降低内存浪费

?:可以声明一个子表达式为非捕获组

var str = 'abcd0123ABCD';

var reg = /(?:[a-z]+)(\d+)([A-Z]+)/g;

reg.test(str); // true

console.log(RegExp.$0); // undefined

console.log(RegExp.$1); // 0123

console.log(RegExp.$2); // ABCD

可以看到,(?:[a-z]+)将这个子表达式声明成了非捕获组,因此捕获组的编号直接跳过了它,从下一个(\d+)开始

.、\s和\S

首先说下.

定义是除\n以外的任何字符

但是,在一些Chrome、Firefox等内核中,代表\n和\r以外的字符

如果要匹配.本身,请用\.

再说说\s与\S

\s是匹配所有的空白字符,包括空白、换行、tab缩进等所有空白

\S是指除了空白以外的任何字符(和.区别下,.里面还多了一部分空白)

那如何匹配所有字符呢?

(.|\n)或者是[\s\S](推荐用法)

请不要试图使用[.\n]或[\.\n],这种写法只表示小数点或\n字符中的一个

示例

请写一个表达式,去除多行注释

var str = '\

var a = 1; \r\n\

/\** \r\n\

* 这里是注释 \r\n\

*/\r\n\

var b = 2;\r\n\

console.log(a)';

var reg = xxx;

str = str.replace(reg, '');

解答

var reg = /\/\*{1,}[\s\S]*\*\//g;

这里就用的了用[\s\S]来匹配所有的字符(因为仅仅是.是无法匹配\r\n的)

\b 单词边界

\b匹配单词边界,不匹配任何字符

简单的说,\b匹配的位置,一侧是构成单词的字符,另一侧是非单词字符,字符串的开始或结束

而其中单词的判断就是\w的匹配范围(正常a-zA-Z0-9_,JS举例)

注,有一特例,在字符组中[\b]表示的是退格符

特点

零宽,即匹配的是位置而不是字符

以\w来界定单词

字符组中是退格符的意思

示例

var str = 'abc_d=efg+hij哈opq%';

var reg = /.\b./g;

// ["d=", "g+", "j哈", "q%"]

str.match(reg);

可以看到,分别在如下几处有单词分界

d和=直接有一个分界

g和+之间

j和哈

q和%

\转义

var str = 'ab\\cd'; // 字符串 ab\cd

var str2 = 'ab\\\\cd'; // 字符串 ab\\cd

var reg = /ab\\\\cd/;

var reg2 = new RegExp('ab\\\\cd');

reg.test(str); // false

reg.test(str2); // true

reg2.test(str); // true

reg2.test(str2); // false

出现\的地方,得多加注意,需要梳理清楚转义逻辑,通过上例可以看到,在正则中出现的\和在字符串中出现的\意义不一样

reg中,\出现在正则中,所以\\\\的意思就是匹配\\字符串,所以测试str2通过,str失败

reg2中,\出现在字符串中,所以\\\\的意思\\,然后构建为正则表达式,最终在正则中是\\,也就是匹配\字符串本身,所以测试str通过,str2失败

附录

博客

初次发布2017.07.31于个人博客

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值