7. 正则表达式必知必会-使用子表达式
7.1 什么是子表达式
第5章学习了匹配字符第连续多次匹配。
现在来匹配
。
const str = 'This is some text text. This is some text text.';
const reg = / {2,}/g;
let match;
while ((match = reg.exec(str))) {
console.log(match[0]);
}
// 没有匹配到
{2,} 仅作用于紧挨着的字符——分号,所以匹配的是 ;
这样的字符,无法匹配
。
7.2 子表达式
子表达式是一个更大的表达式的一部分,把表达式划分为一系列子表达式是为了将子表达式当作独立元素来使用。
子表达式用 () 括起来。
const str = 'This is some text text. This is some text text.';
const reg = /( ){2,}/g;
let match;
while ((match = reg.exec(str))) {
console.log(match[0]);
}
//
匹配 IP 地址。
const str = "The server's IP is 192.168.88.99";
const reg = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/; // \d{1,3} 表示匹配1-3位数字
console.log(reg.exec(str)[0]); // 192.168.88.99
\d{1,3}. 重复了三次。
const str = "The server's IP is 192.168.88.99";
const reg = /(\d{1,3}\.){3}\d{1,3}/; // 把\d{1,3}\.放到圆括号中,表示一个子表达式。{3}表示前面的子表达式重复3次
console.log(reg.exec(str)[0]); // 192.168.88.99
匹配年份。
const str = 'id: 042, sex: m, dob: 1967-08-17, status: active.';
const reg = /19|20\d{2}/; // <-- 认为是 19 或 20加两位数
console.log(reg.exec(str));
// ["19", index: 22, input: "id: 042, sex: m, dob: 1967-08-17, status: active.", groups: undefined]
将 19|20 归为子表达式
const str = 'id: 042, sex: m, dob: 1967-08-17, status: active.';
const reg = /(19|20)\d{2}/; // <-- 将 19|20 归为子表达式
console.log(reg.exec(str));
// ["1967", "19", index: 22, input: "id: 042, sex: m, dob: 1967-08-17, status: active.", groups: undefined]
7.3 子表达式的嵌套
const reg = /(\d{1,3}\.){3}\d{1,3}/; // 匹配 IP 地址的正则
上面的正则是我们之前用过的,但是匹配 IP 还是有些问题。
IP 地址里每组数值的范围在 0-255 之间,可是上面的正则可以匹配 300,425 这样的数值。
注意:把必须匹配的情况考虑周全并写出一个匹配结果符合预期的正则很容易,但把不需要匹配的也考虑周全并把他们排除在外要困难得多。
IP 地址必须匹配且只能匹配的规则:
- 任何一个 1 位 或 2 位数字
- 任何一个以 1 开头的 3 位数字
- 任何一个以 2 开头,第二位数在 0-4 之间的数字
- 任何一个以 25 开头,第三位数字在 0-5 之间的数字
const str = 'The ip is 192.168.23.44';
const reg = /(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))/;
console.log(reg.exec(str)[0]); // 192.168.23.44
\d{1,2}
: 任何一个 1 位 或 2 位数字1\d{2}
: 任何一个以 1 开头的 3 位数字2[0-4]\d
: 任何一个以 2 开头,第二位数在 0-4 之间的数字25[0-5]
: 任何一个以 25 开头,第三位数字在 0-5 之间的数字