前端正则学习记录
JavaScript正则
修饰符
修饰符用于执行不区分大小写和全局的搜索:
修饰符 | 描述 |
---|---|
g | 执行全局匹配(查找所有匹配而不是在第一个匹配后停止)。 |
i | 执行不区分大小写的匹配。 |
d | 执行子字符串匹配。 |
m | 执行多行匹配。 |
方括号
方括号用于查找某个范围内的字符:
表达式 | 描述 |
---|---|
[abc] | 查找括号之间的任何字符。 |
[^abc] | 查找任何不在方括号之间的字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
[^0-9] | 查找任何不在括号内的字符(任何非数字)。 |
(x|y) | 查找任何指定的选项。 |
元字符
元字符是具有特殊含义的字符:
元字符 | 描述 |
---|---|
. | 查找单个字符,除了换行符或行终止符。 |
\w | 查找单词字符。 |
\W | 查找非单词字符。 |
\d | 查找数字。 |
\D | 查找非数字字符。 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\b | 在单词的开头/结尾查找匹配项,开头如下:\bHI,结尾如下:HI\b。 |
\B | 查找匹配项,但不在单词的开头/结尾处。 |
\0 | 查找 NULL 字符。 |
\n | 查找换行符。 |
\f | 查找换页符。 |
\r | 查找回车符。 |
\t | 查找制表符。 |
\v | 查找垂直制表符。 |
\xxx | 查找以八进制数 xxx 规定的字符。 |
\xdd | 查找以十六进制数 dd 规定的字符。 |
\udddd | 查找以十六进制数 xxxx 规定的 Unicode 字符。 |
量词
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{X} | 匹配包含 X 个 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 至 Y 个 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 个 n 的序列的字符串。 |
n$ | 匹配任何以 n 结尾的字符串。 |
^n | 匹配任何以 n 开头的字符串。 |
?=n | 匹配任何其后紧接指定字符串 n 的字符串。 |
?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。 |
RegExp 对象属性
属性 | 描述 |
---|---|
constructor | 返回创建 RegExp 对象原型的函数。 |
global | 检查是否设置了 “g” 修饰符。 |
ignoreCase | 检查是否设置了 “i” 修饰符。 |
lastIndex | 规定开始下一个匹配的索引。 |
multiline | 检查是否设置了 “m” 修饰符。 |
source | 返回 RegExp 模式的文本。 |
RegExp 对象方法
方法 | 描述 |
---|---|
compile() | 在 1.5 版中已弃用。编译正则表达式。 |
exec() | 测试字符串中的匹配项。返回第一个匹配项。 |
test() | 测试字符串中的匹配项。返回 true 或 false。 |
toString() | 返回正则表达式的字符串值。 |
RegExp 对象描述
RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。
直接量语法
/pattern/attributes
创建 RegExp 对象的语法:
new RegExp(pattern, attributes);
参数
参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。
返回值
一个新的 RegExp 对象,具有指定的模式和标志。如果参数 pattern 是正则表达式而不是字符串,那么 RegExp() 构造函数将用与指定的 RegExp 相同的模式和标志创建一个新的 RegExp 对象。
如果不用 new 运算符,而将 RegExp() 作为函数调用,那么它的行为与用 new 运算符调用时一样,只是当 pattern 是正则表达式时,它只返回 pattern,而不再创建一个新的 RegExp 对象。
抛出
SyntaxError - 如果 pattern 不是合法的正则表达式,或 attributes 含有 “g”、“i” 和 “m” 之外的字符,抛出该异常。
TypeError - 如果 pattern 是 RegExp 对象,但没有省略 attributes 参数,抛出该异常。
支持正则表达式的 String 对象的方法
方法 | 描述 |
---|---|
search | 检索与正则表达式相匹配的值。 |
match | 找到一个或多个正则表达式的匹配。 |
replace | 替换与正则表达式匹配的子串。 |
split | 把字符串分割为字符串数组。 |
案例测试
- jc-demo1 - 转义字符
console.log("双引号: \""); // 双引号: "
console.log("单引号: \'"); // 单引号: '
console.log("转义符: \\"); // 转义符: \
- jc-demo2 - 多行字符串
document.body.innerHTML = "
<div></div>
<span></span>
"; // 直接这么写 会报错
document.body.innerHTML =
"<div></div>" +
"<span></span>";
document.body.innerHTML = "\
<div></div>\
<span></span>\
";
// 直接使用模板字符串 更香
document.body.innerHTML = `
<div></div>
<span></span>`;
- jc-demo3 - ignoreCase
var reg = /abc/; // new RegExp('abc');
var str = 'abcd';
reg.test(str); // true
var reg = /abc/; // new RegExp('abc');
var str = 'abcd';
reg.test(str); // true
var reg = /abce/; // new RegExp('abce');
var str = 'abcd';
reg.test(str); // false
var reg = /abcd/i; // new RegExp('abcd', 'i');
// i ==> ignoreCase ==> 忽略大小写
var str = 'ABCD';
reg.test(str); // true
- jc-demo4 - 正则表达式的创建
var reg = /abc/;
var reg1 = new RegExp('abc');
reg === reg1; // falsevar reg = /abc/;
var reg1 = new RegExp(reg);
reg === reg1; // falsevar reg = /abc/;
var reg1 = RegExp(reg);
reg === reg1; // truevar reg = /abc/;
var reg1 = reg;
reg === reg1; // true
- jc-demo5 - global
var reg = /ab/;
var str = "abababab";
str.match(reg); // ["ab"]var reg = /ab/g;
var str = "abababab";
str.match(reg); // ["ab", "ab", "ab", "ab"]
- jc-demo6 - multiline
var reg = /a/g;
var str = "abcdea";
str.match(reg); // ["a", "a"]var reg = /^a/g;
var str = "abcdea";
str.match(reg); // ["a"]var reg = /^a/g;
var str = "abcde\na";
str.match(reg); // ["a"]var reg = /^a/gm;
var str = "abcde\na";
str.match(reg); // ["a", "a"]
- jc-demo7 - 方括号
var str = "12309u9873zpoixcuypiouqwer";
var reg = /[1234567890][1234567890][1234567890]/g;
// 一对 [] 表示一位 [] 的里面装的是范围
str.match(reg); // ["123", "987"]var reg = /[ab][cd][d]/g;
var str = "abcd";
str.match(reg); // ["bcd"]var reg = /[0-9A-Za-z][cd][d]/g; // 该正则表达式也可以写成: /[0-9A-z][cd][d]/g
var str = "ab1cd";
str.match(reg); // ["1cd"]var reg = /[^a][^b]/g; // 第一位不是a 第二位不是b
var str = "ab1cd";
str.match(reg); // ["b1", "cd"]var reg = /(abc|bcd)[0-9]/g; // | 表示: 或
var str = "abc2";
str.match(reg); // ["abc2"]
- jc-demo8 - \w 和 \W
\w === [0-9A-z_]
\W === [^0-9A-z_]var reg = /\wcd2/g;
var str = "bcd2";
str.match(reg); // ["bcd2"]var reg = /\Wcd2/g;
var str = "bcd2";
str.match(reg); // nullvar reg = /\Wcd2/g;
var str = "b*cd2";
str.match(reg); // ["*cd2"]
- jc-demo9 - \d 和 \D
\d === [0-9]
\D === [^0-9]var reg = /\d\d\d/g;
var str = "123";
str.match(reg); // ["123]var reg = /[\w\d]/g; // 直接写 [\w] 也就OK了 因为在 \d 里的 一定在 \w 里
var str = "s";
str.match(reg); // ["s"]
- jc-demo10 - \s 和 \S
\s === [\t\n\r\v\f ] // 注意 结尾还有一个空格
\S === [^\t\n\r\v\f ]var reg = /\tc/g;
var str = "abc cdefgh"; // 手动按的 tab键
str.match(reg); // null
// 之所以不能匹配 是因为tab键被识别为空格了 比如在 vscode 中 就可以将 tab 键设置为 4 个空格
// 即: 当我们在 vscode 中 按下 tab 键时 它将自动转化为 4 个空格 就好比我们按了 4 下空格键一样var reg = /\tc/g;
var str = "abc cdefgh"; // 复制chrome控制台输出的 \t
str.match(reg); // [" c"]var reg = /\tc/g;
var str = "abc\tcdefgh";
str.match(reg); // [" c"]
- jc-demo11 - \b 和 \B
var reg = /\bc/gi;
var str = "abc Cde fgh";
str.match(reg); // ["C"]var reg = /\bcde\b/g;
var str = "abc cde fgh";
str.match(reg); // ["cde"]var reg = /\bcde\B/gi;
var str = "abc cde Cdefgh";
str.match(reg); // ["Cde"]
- jc-demo12 - \uxxxx
字符编码笔记:ASCII,Unicode 和 UTF-8 阮一峰
1. Unicode编码一共有16层
\u010000 - \u01ffff
\u020000 - \u02ffff
...
\u0f0000 - \u0fffff
\u100000 - \u10ffff
我们一般使用的也就是第一层
若使用的是第一层 那么书写时 可以直接省略一开始的 01 \u后面只要写4位即可var reg = /\u8001\u9093\u8eab\u4f53\u597d/g;
var str = "老邓身体好";
str.match(reg); // ["老邓身体好"]var reg = /[\u0000-\uffff]/g; // 所有字符
var str = "老邓身体好";
str.match(reg); // ["老", "邓", "身", "体", "好"]
所有字符还有很多种写法: [\s\S] [\w\W] [\d\D] 等等
- jc-demo13 - . 和 \r\n
. === [^\r\n]var reg = /./g;
var str = "老邓 身体好";
str.match(reg); // ["老", "邓", " ", "身", "体", "好"]
- jc-demo14 - 量词
var reg = /\w+/g; // + 出现1次或多次 {1, }
var str = "abc";
str.match(reg); // ["abc"]var reg = /\w*/g; // * 出现0次或多次 {0, }
var str = "abc";
str.match(reg); // ["abc", ""]
// 最后有个空串是因为 g 是全局匹配
// 匹配出"abc"后 光标就停在了c后面 这个c后面还有一段逻辑上的距离
// * 表示出现0次或多次 所以到最后 还会再匹配一次 即便内容是空var reg = /\d*/g;
var str = "abc";
str.match(reg); // ["", "", "", ""]
// 一开始 光标在 a前面
// 然后是 b前面
// 然后是 c前面
// 然后是 c后面
// 思考: 为何上一个例子中的 \w 不会匹配出4个空格加abc呢?
// 答: 这涉及到贪婪模式的概念 ==> 后面有具体介绍
// 其实 默认情况下 是 贪婪模式 那么如何使用 非贪婪模式呢?
// 在量词后面加 ? 即可var reg = /\w*?/g; // 量词后面加 ? 开启非贪婪模式
var str = "abc";
str.match(reg); // ["", "", "", ""]var reg = /\w+/g;
var str = "aaaaaaaaaaaa";
str.match(reg); // ["aaaaaaaaaaaa"]var reg = /\w?/g; // 出现0次或1次 {0, 1}
var str = "abc";
str.match(reg); // ["a", "b", "c", ""]var reg = /\w{3}/g;
var str = "aaaaaa";
str.match(reg); // ["aaa", "aaa"]var reg = /\w{3,5}/g;
var str = "aaaaaaaaaaaaaa";
str.match(reg); // ["aaaaa", "aaaaa", "aaaa"]
- jc-demo15 - ^ 和 $
var reg = /^abc/g;
var str = "abcde";
str.match(reg); // ["abc"]var reg = /de$/g;
var str = "abcde";
str.match(reg); // ["de"]var reg = /^abc$/g;
var str = "abcabc";
str.match(reg); // nullvar reg = /^abc$/g;
var str = "abc";
str.match(reg); // ["abc"]
- 阿里巴巴笔试题 写一个正则表达式,检验一个字符串首尾是否含有数字。
var reg = /^\d|\d$/g; // 首有 或 尾有
检验一个字符串首尾是否都含有数字
var reg = /^\d[\s\S]*\d$/g;
- jc-demo16 - exec()
var reg = /ab/g;
var str = "abababab";
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 2
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 2, input: "abababab", groups: undefined] 4
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 4, input: "abababab", groups: undefined] 6
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 6, input: "abababab", groups: undefined] 8
console.log(reg.exec(str), reg.lastIndex); // null 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 2/*
index -> 本次匹配的开始位置
lastIndex -> 下一次匹配的开始位置(可读可写) */var reg = /ab/;
var str = "abababab";
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
console.log(reg.exec(str), reg.lastIndex); // ["ab", index: 0, input: "abababab", groups: undefined] 0
- jc-demo17 - 反向引用
var reg = /(\w)\1\1\1/g; // 第一个捕获组 (\w) 会记录匹配的内容 \1 表示引用第一个捕获组捕获的内容 一共重复了3次
var str = "aaaabbbb";
str.match(reg); // ["aaaa", "bbbb"]var reg = /(\w)\1\1\1/g; // var reg = /(\w)(\w)(\w)(\w)/g; 注意: 这两种写法是不同的
var str = "aaccbbbb";
str.match(reg); // ["bbbb"]var reg = /(\w)\1(\w)\2/g;
var str = "aabb";
str.match(reg); // ["aabb"]var reg = /(\w)\1(\w)\2/g;
var str = "aabb";
console.log(reg.exec(str)); // ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]
- jc-demo18 - RegExp 和 String
- match
var reg = /(\w)\1(\w)\2/; // 不加g
var str = "aabb";
console.log(str.match(reg)); // ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]var reg = /(\w)\1(\w)\2/g; // 加g
var str = "aabb";
console.log(str.match(reg)); // ["aabb"]
- search
var reg = /(\w)\1(\w)\2/g;
var str = "edaabbbbee";
console.log(str.search(reg)); // 2
console.log(str.search(reg)); // 2 和有没有g无关 找的都是最近的满足条件的匹配项
// search 只管能否匹配到 若匹配不到 那么返回 -1
- split
// 想拆分字符串 规则是 将连续出现的字符拆开
var reg = /(\w)\1/g;
var str = "bntgjzeaasrykzeaskl,zntgjzeasrykkzeaskl,";
console.log(str.split(reg)); // ["bntgjze", "a", "srykzeaskl,zntgjzeasry", "k", "zeaskl,"]
// 我们想要的返回结果是: ["bntgjze", "srykzeaskl,zntgjzeasry", "zeaskl,"]
// 但是 split 将捕获组中的内容也给返回了
// 这样就遇到了一个问题 若不用捕获组 那么无法反向引用
// 也就是无法选中两个连续出现的字母 但是这样做的话 匹配内容不会作为返回结果返回
// ... 这个问题 暂且先放一放 不想了
// 刚花了1个多小时 想要封装一个函数 这个函数需要传入两个参数
// 参数1: 是一个字符串
// 参数2: 是一个字符串数组 (数组的每一项 都是一个字符串)
// 功能: 按照参数2的每一项 分割 参数1
// eg:
// 参数1: '11jdaskdlqwe22askldjzc33sdlkfjAAoaps'
// 参数2: ["11", "22", "33", "AA"] 实际上 str.match(/(\w)\1/g) 就可以获取到该数组
// 结果: ["jdaskdlqwe", "askldjzc", "sdlkfj", "oaps"]var reg = /(\w)\1/g;
var str = "bntgjzeaasrykzeaskl,zntgjzeasrykkzeaskl,";
var newStr = str.replace(reg, "~~");
newStr.split("~~"); // ["bntgjze", "srykzeaskl,zntgjzeasry", "zeaskl,"]var reg = /f/g;
var str = "avfdw";
console.log(str.split(reg)); // ["av", "dw"]
- replace
var str = "aa";
console.log(str.replace("a", "b")); // bavar reg = /a/;
var str = "aa";
console.log(str.replace(reg, "b")); // bavar reg = /a/g;
var str = "aa";
console.log(str.replace(reg, "b")); // bbvar reg = /(\w)\1(\w)\2/g;
var str = "aabb";
console.log(str.replace(reg, "$2$2$1$1")); // bbaavar reg = /(\w)\1(\w)\2/g;
var str = "aabb";
console.log(str.replace(reg, function ($, $1, $2) { // 第一个参数 是整个正则表达式的匹配结果return $2 + $2 + $1 + $1;// return $2$2$1$1; 不能这么写 这么写不符合JavaScript语法规范 毕竟$1和$2也是变量
})); // bbaa
- 练习: 把 the-first-name 变成小驼峰式大写
var reg = /-(\w)/g;
var str = "the-first-name";
console.log(str.replace(reg, function ($, $1) {// console.log("a"); // 会打印两次 因为一共有两个匹配项 所以 function 执行了两次return $1.toUpperCase();
})); // theFirstName
- jc-demo19 - 正向预查(断言)/非正向预查(断言)
var reg = /a(?=b)/g;
var str = "abaaaaaa";
str.match(reg); // ["a"]var reg = /a(?!b)/g;
var str = "abaaaaaa";
str.match(reg); // ["a", "a", "a", "a", "a", "a"]
- jc-demo20 - 非贪婪匹配
var reg = /\w+?/g;
var str = "aaa";
str.match(reg); // ["a", "a", "a"]var reg = /\w??/g;
var str = "aaa";
str.match(reg); // ["", "", "", ""]
- jc-demo21 - 补充
var reg = / /g;
var str = "a aa";
str.match(reg); // [" "]
- 练习: 字符串去重
var reg = /(\w)\1*/g;
var str = "aaaaaabbbbbbbbbcccccccc";
console.log(str.replace(reg, "$1")); // abc
- 笔试题: (2014 百度试题,成哥有史以来见过最难的题) 有一个数字 100000000000 现在要求科学计数法 从后往前每隔三位打个点
var str = "100000000000";
var reg = /(?=(\B)(\d{3})+$)/g;
console.log(str.replace(reg, ".")); // 100.000.000.000
代码测试记录
// 转义符号使用\n换行 转义无法显示的字符
// const abc = "abc\n123";
// /*
// abc
// 123
// */
// console.log(abc);
// 使用转义符号字符串换行
// const abc = "<div>\
// abc\
// </div>";
// console.log(abc);/*静态属性RegExp.lastIndex
该索引表示从哪里开始下一个匹配 */
// const s = "1234abc123ABC";
// const reg = /\d+/gmi; // 贪婪模式 没有加量词 ?
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex);
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex);
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex);
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex);
// 0 true 4
// 4 true 10
// 10 false 0 这一次是从A匹配到结尾C 发现没有匹配项 所以 reg.test(s) 返回 false
// 0 true 4
/* 说明:
1. 一开始从下标为0的位置开始匹配 也就是 1
2. 第一次test结束之后 此时索引为与第一次匹配结束的位置 4 也就是 a
3. 当匹配到结尾之后 再重头开始匹配
小结:
1. 开始索引是0;
2. 下一次索引是上一次的结束位置;
3. 匹配到结尾后 会重头开始继续匹配 */// RegExp.lastIndex 是可读可写的
// const s = "1234abc123ABC";
// const reg = /\d+/gmi;
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex); // 0 true 4
// reg.lastIndex = 0;
// console.log(reg.lastIndex, reg.test(s), reg.lastIndex); // 0 true 4// 计算匹配次数
// const s = "1234abc123ABC";
// const reg = /\d+/gmi;
// const n = 0;
// while (reg.test(s)) {
// n++;
// }
// console.log(`匹配了${n}次`); // 匹配了2次// // 计算匹配次数与匹配到的内容 +表示匹配字符一次或多次 ?表示非贪婪模式 不加? 表示贪婪模式
// const reg = /\d+?/gmi;
// const s = "1234abc567ABC";
// let n = 0;
// while (reg.test(s)) {
// n++;
// }// console.log(`匹配了${n}次`); // 匹配了7次
// while (result = reg.exec(s)) {
// console.log(result[0]); // 依次输出 1234567
// }// const reg = /\d+/g;
// const s = "1234abc567ABC";// // 得到所有的匹配结果和位置
// while (result = reg.exec(s)) { // result = reg.exec(s) 这整个表达式的返回值是 result 的值
// console.log(`匹配结果:${result[0]},出现位置:${result.index}`);
// }
// // 匹配结果:1234,出现位置:0
// // 匹配结果:456,出现位置:7// /* String.prototype.search() ==> 对正则表达式和指定字符串进行匹配搜索,返回第一个出现的匹配项的下标。 */
// const s = "abc567ABC";
// const result = s.search(/\d+/g);
// console.log(result); // 3// const s = "hello world\tjavascript\nyes";
// const result = s.split(/[, \n\t]/); // 将所有分割结果以字符串数组的形式返回
// console.log(result); // (3) ['hello', 'world', 'javascript', 'yes']// // 第二个参数n的作用 ==> 取分割后的前n个
// const result2 = s.split(/[, \n\t]/, 2); // 取前两个
// console.log(result2); // (2) ['hello', 'world']/* String.prototype.replace ==> 被用来在正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串。 */
// const s = "hello World ! Javascript.";
// // 将第一个空格字符替换为 逗号,
// console.log(s.replace(" ", ",")); // hello,World ! Javascript. (默认非全局)
// // console.log(s.replace(new RegExp(" "),","));
// // replace 不会改变原始字符串 而是返回一个新的字符串
// console.log(s); // hello World ! Javascript.// const s = "hello World ! Javascript.";
// // 将全部不可见字符替换为 逗号,
// console.log(s.replace(new RegExp(/\s/, "g"), ",")); // hello,World,!,Javascript.
// // console.log(s.replace(/\s/g,","));// let s = "hello world";
// // 将单词的首字符 替换为 逗号
// s = s.replace(/\b[a-z]/g, ",");
// console.log(s); // ,ello ,orld/* str.replace 语法 ==> 第二个参数可以是一个函数
str.replace(regexp|substr, newSubStr|function)
*/
// let s = "hello world";
// // 将单词的首字符 替换为 逗号
// s = s.replace(/\b[a-z]/g, function (match) {
// console.log(match); // 第一个参数表示匹配的内容
// return ","; // 返回值 作为替换内容
// });
// // h
// // w
// console.log(s); // ,ello ,orld// let s = "hello world";
// // 将单词的首字符 变成大写
// s = s.replace(/\b[a-z]/g, function (match) {
// return match.toUpperCase();
// });
// console.log(s); // Hello World// let s = "hello world\tjavascript\nyes";
// // 将字符串中的空白字符去掉 并 转换为大驼峰的形式
// s = s.replace(/\s*\b[a-z]\s*/g, function (match) {
// console.log(match); // h w j y
// return match.toUpperCase().trim();
// });
// console.log(s); // HelloWorldJavascriptYes// // 书写一个正则表达式,去匹配一个字符串,得到匹配的次数,和匹配的结果
// let s = "433afdsaf34542fsdssfsd234"
// console.log(s.match(/\d+/g))// 得到一个字符串中中文字符的数量
// let s = "fgdgg啊手动sdf阀梵蒂冈sd234";
// console.log(s.match(/[\u4e00-\u9fa5]/g).length);// // 过滤敏感词,有一个敏感词数组,需要将字符串中出现的敏感词替换为四个星号
// let senWords = ["色情", "暴力", "卢本伟", "贸易战"]; // 实际开发中是 从数据库引入 存放在数组中操作
// //将字符串中敏感词汇替换为指定的字符串
// function removeSensitiveWords(s, rep) {
// // let reg = new RegExp(`(${色情|暴力|卢本伟|贸易战})+`, "g"); // 不能写死
// const reg = new RegExp(`(${senWords.join("|")})+`, "g"); // + ==> 连续的敏感词汇 只替换一次
// return s.replace(reg, rep);
// }// console.log(removeSensitiveWords("sdffs色情暴力sfsfs卢本伟牛逼dsdf贸易战sf防火规范个", "****"));
// // sdffs****sfsfs****牛逼dsdf****sf防火规范个// 匹配章节
// 使用(h2{第$章}+p*5>lorem100)*5 生成5个章节
// const html = `...`;
// const reg = /<h2>第\d+章<\/h2>/g;
// const result = html.match(reg);
// if (result) {
// console.log(result.length); // 10
// } else {
// console.log(0);
// }
// console.log(result);
// (5) ["<h2>第1章</h2>", "<h2>第2章</h2>", "<h2>第3章</h2>", "<h2>第4章</h2>", "<h2>第5章</h2>"]/*
1. 捕获组用小括号包裹的部分叫做捕获组,捕获组会出现在匹配结果中捕获组可以命名,叫做具名捕获组非捕获组
2. 反向引用在正则表达式中,使用某个捕获组,\捕获组编号
3. 正向断言(预查)检查某个字符后面的字符是否满足某个规则,该规则不成为匹配结果,并且不称为捕获组
4. 负向断言(预查)检查某个字符后面的字符是否不满足某个规则,该规则不成为匹配结果,并且不称为捕获组
*/// 用小括号包裹起来的部分叫做捕获组, 捕获组会出现在匹配结果中
// const reg = /(\d[a-z])([a-z]+)/g;
// const s = "2afsdf-5fdgdfg-9asddf";
// while (result = reg.exec(s)) {
// console.log(result);
// }
// // (3) ["2afsdf", "2a", "fsdf", index: 0, input: "2afsdf-5fdgdfg-9asddf", groups: undefined]0: "2afsdf"1: "2a"2: "fsdf"groups: undefinedindex: 0input: "2afsdf-5fdgdfg-9asddf"length: 3__proto__: Array(0)
// // (3) ["5fdgdfg", "5f", "dgdfg", index: 7, input: "2afsdf-5fdgdfg-9asddf", groups: undefined]
// // (3) ["9asddf", "9a", "sddf", index: 15, input: "2afsdf-5fdgdfg-9asddf", groups: undefined]
// // 结果数组中下标 0 的成员 仍然表示整个正则表达式的匹配结果
// // 捕获组 ==> 会出现在匹配结果的数组里头
// // 多出来的两个下标 1 和 2 分别表示的是两个小括号() 也就是捕获组 匹配的内容// 需求: 得到每一个日期,并得到每个日期的年月日
// const s = "2015-5-1, 2019-6-19, 2000-04-28";
// const reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
// while (result = reg.exec(s)) {
// console.log(result[0], result[1], result[2], result[3]);
// }
// // 2015-5-1 2015 5 1
// // 2019-6-19 2019 6 19
// // 2000-04-28 2000 04 28// 捕获组可以命名 ==> 具名捕获组
// const s = "2015-5-1, 2019-6-19, 2000-04-28";
// const reg = /(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})/g;
// while (result = reg.exec(s)) {
// console.log(result.groups, result.groups.year, result.groups.month, result.groups.day);
// }
// // {year: "2015", month: "5", day: "1"} "2015" "5" "1"
// // {year: "2019", month: "6", day: "19"} "2019" "6" "19"
// // {year: "2000", month: "04", day: "28"} "2000" "04" "28"// // 非捕获组模式 ==> ?: ==> 表示这个加小括号的 不是一个捕获组 而仅仅把其看做是一个整体
// // 可以提高执行效率
// var s = "2015-5-1, 2019-6-19, 2000-04-28";
// var reg = /(?:\d{4})-(?:\d{1,2})-(\d{1,2})/g;
// while (result = reg.exec(s)) {
// console.log(result[0], result[1], result[2], result[3]);
// }
// // 2015-5-1 1 undefined undefined
// // 2019-6-19 19 undefined undefined
// // 2000-04-28 28 undefined undefined// 在 replace 中使用捕获组 替换 年月日格式 年-月-日 ==> 年/月/日 可以使用$1 $2 $3这种获得捕获的匹配项
// var s = "2015-5-1,- 2019-6-19,- 2000-04-28";
// // 需求 年-月-日 ==> 年/月/日
// var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
// s = s.replace(reg, function (match, g1, g2, g3) { // 1: 匹配结果 2: 第一个捕获组 3...
// console.log(match, g1, g2, g3);
// return `${g1}/${g2}/${g3}`;
// })
// console.log(s); // 2015/5/1,- 2019/6/19,- 2000/04/28
// 在 replace 中使用捕获组 的另一种写法
// var s = "2015-5-1,- 2019-6-19,- 2000-04-28";
// // 需求 年-月-日 ==> 年/月/日
// var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
// s = s.replace(reg, "$1/$2/$3"); // 利用特殊字符 $1 表示第一个捕获组 $2 ...
// console.log(s); // 2015/5/1,- 2019/6/19,- 2000/04/28// // 反向引用 ==> 在正则表达式中 使用某个捕获组 ==> 使用: \捕获组编号 捕获ABAB这种
// var reg = /(\d{2})\1\1/; // var reg = /(\d{2})(\d{2})(\d{2})/; 两种写法类似 但又有所不同
// var s = "131313";
// var s1 = "202020";
// var s2 = "202120";// console.log(reg.test(s)); // true
// console.log(reg.test(s1)); // true
// console.log(reg.test(s2)); // false// var reg = /(\d{2})\1\1/; // 写法一
// // var reg = /(\d{2})(\d{2})(\d{2})/; // 写法二
// // 第二种写法 有三个捕获组 第一种写法只有一个捕获组
// var s = "131313";// console.log(reg.exec(s));
// // (2) ["131313", "13", index: 0, input: "131313", groups: undefined]
// // 注意: 此时只有一个捕获组// // 反向引用的应用举例 ==> 面试题 找出该字符串中连续的字符 (不包含只出现一次的字符)
// var s = "aaaaaaaabbbbbbbbbccccccdefgggggggg";
// // 需求: 找出该字符串中连续的字符 (不包含只出现一次的字符)
// var reg = /(\w)\1+/g;
// while (result = reg.exec(s)) {
// // console.log(result);
// console.log(result[1]);
// }
// // a
// // b
// // c
// // g// // 正向断言(预查) ==> ?= ==> 检查某个字符后面的字符是否满足某个规则, 该规则不成为匹配结果, 并且不称为捕获组
// var s = "sdfsdf3434343sdfsa545454dfsdfsfsd6754";
// // 需求: 找字母 要求此字母的后面是数字
// var reg = /[a-zA-Z](?=\d+)/g;
// while (result = reg.exec(s)) {
// console.log(result); // f a d
// }
// // ["f", index: 5, input: "sdfsdf3434343sdfsa545454dfsdfsfsd6754", groups: undefined]
// // ["a", index: 17, input: "sdfsdf3434343sdfsa545454dfsdfsfsd6754", groups: undefined]
// // ["d", index: 32, input: "sdfsdf3434343sdfsa545454dfsdfsfsd6754", groups: undefined]// // 负向断言(预查) ==> 检查某个字符后面的字符是否不满足某个规则, 该规则不成为匹配结果, 并且不称为捕获组
// var s = "afg43223444wr423424243";
// // 需求: 找字母 要求改字母后面跟的不是数字
// var reg = /[a-zA-Z](?!\d+)/g;
// while (result = reg.exec(s)) {
// console.log(result); // a f w
// }// 判断密码强度(预备知识点, 下面将封装函数judgePwd来实现)
// 要求密码中必须出现小写字母、大写字母、数字、特殊字符(!@#_,.),6-12位
// var s = "asdfsdAf234.";
// var s1 = "asdfsdAf234";
// var reg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#_,.]).{6,12}$/;
// // 预查 ==> 注意: 只做检查 不会消耗(也就是说 下一次开始预查的时候 还是从头开始)
// // 这一点不容易理解 举例来说: (?=.*[a-z]) 会从头到尾走一遍 (?=.*[A-Z]) 也会从头到尾走一遍 后面的都会 ...
// console.log(reg.test(s)); // true ==> 预查通过
// console.log(reg.test(s1)); // false ==> 预查不通过// 判断密码强度
// 密码长度必须是6-12位
// 出现小写字母、大写字母、数字、特殊字符(!@#_,.) -> 强
// 出现小写字母、大写字母、数字 -> 中
// 出现小写字母、大写字母 -> 轻
// 其他 -> 不满足要求
// function judgePwd(pwd) {
// if (/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#_,.]).{6,12}$/.test(pwd)) {
// return "强";
// } else if (/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,12}$/.test(pwd)) {
// return "中";
// } else if (/^(?=.*[a-z])(?=.*[A-Z]).{6,12}$/.test(pwd)) {
// return "轻";
// } else {
// return "不满足要求";
// }
// }// console.log(judgePwd("asdADFF4.343"));
相关网站
mdn
w3school
部分内容来源js(姬成) - 10. 对象,包装类 - 《0050 - JavaScript(姬成)》 - 极客文档 (geekdaxue.co)