1. 前言
话不多少,下面会列出正则表达式的各种符号标记的解释,并搭配一些案例解释。
2. 符号主讲
2.1 /
正则表达式(下称“正则”)一定是写在/ reg /
中间的,这是必须遵循的基准。
2.2 []
[]可以被理解为范围限定符,<mark>[]仅替代一个字符,[]中的内容限定(扩大)了字符的匹配范围</mark>
var reg = /d[0-9]e/;
// reg会在t_1中从左往右寻找第一个满足``d[0-9]e``的子串,其中[0-9]可以是任意数字
var t_1 = "a1bd2e"; // 输出"d2e"
[]中可以是任意字符,但大部分字符仅用于匹配,只有少部分特殊字符能发挥作用
var reg = /[(s)]/; // 会匹配字符串中的 '('、's'、')',"()"在此处失去特殊作用
var reg_2 = /[^(s)]/; // 会匹配除``(s)``三个字符外的所有字符,^在[]表示除xx以外
var t_1 = "(asb)";
2.3 ()
()可以被理解为区域限定符,<mark>()内字符将被看成一个复合字符进行匹配</mark>
var t_1 = "ababcd(())";
var reg_1 = /(ab){2}/; // 将会匹配 "abab"
var reg_2 = /abab/; // 将会匹配 "abab"
从上面可以看出,使用()便于正则表达式的书写。同时,()
还肩负着另一项功能,那就是<mark>定位捕获</mark>。
以==(?: )==为例,
var t_1 = "abacdfbd";
var reg_1 = /a(?:ba|fb)/;
// 首先 (?:ba|fb)定位到字符串中所有ba,fb子串的首位
// 然后根据正则表达式,匹配符合要求的子串,上例为 aba,输出
var reg_2 = /.(?:ba|fb)./; //猜猜会匹配到什么结果? 如果是/.(?:ba|fb)../呢? 答案写在文章最后
不知道你有没有发现上面的==(?: )<mark>发现和</mark>常规的()写法==作用相同?
其实匹配过程可以理解为两步,分别是定位和捕获,核心思想仍然是匹配,下面是全部用法:
-
?: 相等匹配,并带回定位项,可省略
-
?= 定位子串首位的相等匹配,但不带回定位项,下同
-
?! 定位子串首位的不相等匹配
-
?<= 定位子串末位的相等匹配
-
?<! 定位子串末位的不相等匹配
2.4 {}
{}可以被理解为数量限定符,<mark>{}修饰前面一个字符的数量</mark>,可以理解为<mark>匹配n个字符的连接</mark>
var t_1 = "ababab{}";
var reg_1 = /(ab){2}/; // abab
var reg_2 = /(ab){1,2}/; // abab ab
var reg_3 = /(ab){2,}/; // ababab
{}格式为{x, y},一般可写为
- {x},匹配确切的 x 个字符
- {x, y},最少匹配x个,最多匹配 y 个
- {x, },最少匹配 x个,无上限匹配
{}格式为{x, y},
注意:
匹配原则适用<mark>长度优先</mark>
var t_1 = "ababababab{}";
var reg_1 = /(ab){1,2}/; // abab abab ab,先匹配2个字符,不存在则匹配1个字符
2.5 其他常用字符
常用修饰字符:
字符 | 描述 |
---|---|
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符 |
^ | 匹配输入字符串的开始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的子表达式零次或多次 |
+ | 匹配前面的子表达式一次或多次 |
? | 匹配前面的子表达式零次或一次 |
| | 或,扩大匹配范围 |
常用转义字符:
字符 | 描述 | 字符 | 描述 |
---|---|---|---|
\b | 匹配一个单词边界,也就是指单词和空格间的位置 | \B | 匹配非单词边界 |
\d | 匹配一个数字字符。等价于 [0-9] | \D | 匹配一个非数字字符。等价于 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等 | \S | 匹配任何非空白字符 |
\w | 匹配字母、数字、下划线 | \W | 匹配非字母、数字、下划线 |
\f | 匹配一个换页符 | \r | 匹配一个回车符 |
\n | 匹配一个换行符 |
2.6 标记
标记也称为修饰符,正则表达式的标记用于指定额外的匹配策略。标记不写在正则表达式里,标记位于表达式之外。
var reg = /abc/g; // 查找所有的匹配项
var reg = /abc/i; // 查找不区分大小写
var reg = /abc/m; // 开启多行匹配,而^和$匹配的只是行的头和尾,而不是字符串的
var reg = /abc/s; // 默认. 是 匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n
3. 答案
var t_1 = "abacdfbda";
var reg = /.(?:ba|fb)./; // 会匹配到abac 和 dfbd,
// 首先定位到ba和bd的首位,然后在此首位前后匹配,.匹配任意字符,注意 ?: 会带回定位项
var reg_2 = /.(?=ba|fb)./; // 会匹配到 ab、df,因为不会带回定位项
var reg_3 = /.(?:ba|fb)../; // 结果为 abacd,你们会想为什么不是abacd和dfbda呢
看下面的例子:
var t_1 = "abcdefghi";
var reg_1 = /(?:ab|ef)../; // 输出结果是 abcd efgh
var reg_2 = /(?:ab|ef).../; // 输出结果是 abcde
// 虽然我也不知道是什么原因,但是分析一下只输出abcde的情况
// 原本应该输出 abcde、efghi,但由于两个子串存在重复,所以只输出了前一个
// 我们可以将这个例子作为规则记住