Souffle js 正则表达式笔记
渡一教育公开课笔记
正则表达式 Regular Expression 在 js 代码中简写为 regexp,
重点它是一个表达式,正则是表达式的修饰词,整体的意思是符合一个规则的表达式,
主要作用是对字符串进行操作、过滤、以及检索校验的一种规则
一、定义和匹配
“正则表达式”的定义有两种方式
1. 直接字面量 /abc/
2. 构造函数 new RegExp('abc')
正则表达式匹配使用的两个方法
1. 正则表达式上的方法 reg.test(str)
2. 字符串上的方法 str.match(reg)
示例,
通过一个“用户名规则的校验”体验正则表达式是如何定义和匹配的,比如输入的用户名必须以数字、字母、下划线,这三种之一开头
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>用户名的校验规则</title> </head> <body> <input type="text" id="username"/> <div id="msg"></div> <script> var username = document.getElementById('username'); var msg = document.getElementById("msg"); username.oninput = function(){ checkedFun(this.value); } function checkedFun(str){ var reg = /^[\dA-z_]/; if(str.match(reg)){ msg.innerText = "符合规则"; }else{ msg.innerText = "用户名只能以数字、字母、下划线开头"; } } </script> </body> </html>
监听 oninput 输入事件,每次输一个字符都会触发,
获取 input 框输入的值是一个字符串,正则表达式对输入的字符串进行校验
^[\dA-z_]
^ 表示以方括号里面的字符开头
[] 方括号代表一个字符,这一个字符可以是数字 \d,可以是字母 A-z,也可以是划线 _
str.match(reg)
使用字符串上的 match 方法实现正则的匹配
1. 输入 abc 匹配成功,返回的是符合规则的的子字符串 ['a', index: 0, input: 'abc', groups: undefined]
2. 输入空格或中文返回 null,表示不符合匹配规则
用构造函数 RegExp 的方式声明正则表达式,参数传的字符串是匹配规则
function checkedFun(str){ var reg = new RegExp('^[\\da-zA-Z_]'); if(reg.test(str)){ msg.innerText = "符合规则"; }else{ msg.innerText = "用户名只能以数字、字母、下划线开头"; } }
注意,
new RegExp('^[\\dA-z_]')
参数是字符串,
在字符串中 \ 斜杠有特殊的含义,表示转义后面的一个字符,
要想实现 \d 的效果,要在加一个斜杠 \\d 转义一下,表示取消后面第二个 \ 斜杠的含义
reg.text(str)
正则表达式上的匹配方法
1. 参数是要校验的字符串,校验字符串是否符合正则规则
2. 返回一个布尔值
体验一些匹配规则
/[3578]$/ $表示以中括号里面的数字3578,任何一个结尾都可以
/[3578]+$/ 量词 + 号代表 1 ~ 多个(* 代表 0 ~ 多个),匹配 3578,1 至多个数字结尾
/^[3578]+$/ 以 3578 开头又以 3578 结尾,输入 3、35、358 等都可以匹配,有一个不是 3578 的字符都是错误
/3578/ 字符串中含一个这样 "3578" 的整体
Ps:
input 元素是行级块元素,既可以设置宽高也不会占满一行,
修改一下 .msg 元素 display: inline-block 就到一行了
二、原子
什么是原子?
组成正则表达式的最小单位就是原子
原子表
语法 | 描述 |
[abc] | 方括号内的任意一个字符 |
[^abc] | 不在方括号内的字符 |
[0-9] | 0-9 之间的数字 |
[a-z] | 任何小写字母 |
[A-Z] | 任何大写字母 |
[A-z] | 大写和小写字母 |
() | 子表达式 |
\uxxx | 查找十六进制数 xxx 规定的 Unicode 字符 |
[\u4e00-\u9fa5] | 所有中文字符 |
参考图片连接 |
方括号跟小括号的区别
[ \dA-z_ ] 代表一个字符,方括号里面的内容是或的关系,任意一个字符可以是数字、可以是字母、可以是下划线
( \dA-z_ ) 并列的关系,要匹配的,先是数字,后面是字母,最后是下划线(小括号也叫子表达式)
模式修饰符
修饰符 | |
i | 代表 ignorecase 忽略大小写 |
m | 代表 multiline 多行匹配 |
g | 代表 global 全局匹配,匹配出所有符合规则的子字符串 |
三、元字符
语法 | 描述 |
. | 代表单个字符,除了换行符和行结束符以外的任意一个字符 |
\w | 小写 w 表示字母、数字、下划线,等价于 [A-Za-z0-9_] |
\W | 非单词字符,就是除了小 \w 以外的字符 |
\d | 数字 |
\D | 非数字 |
\s | 空白字符 |
\S | 非空白字符 |
\b | 单词边界 |
\B | 非单词边界符 |
\n | 换行符 |
\f | 换页符 |
\r | 回车符 |
\t | 制表符 |
\v | 垂直字表符 |
. 点
正则表达式中“点”有特殊的含义,它表示任意一个字符,
除了换行符和行结束符以外,其他的任意一个字符
换行符是 \n,行结束符就是回车 \r,也就是说 \n 和 \r 它匹配不出来
/.ello/
点 . 代表第一个字符,以任意一个字符开始
然后后面必须是 ello
修饰符 g 全局匹配,表示把所有符合条件的全部匹配出来
var str = "hello world, hello duyi, welcome duyi"; var reg = /.ello/g; console.log(str.match(reg)); // ['hello', 'hello']
字符串的 match 方法,返回所有符合条件的“子字符串”是一个数组的形式
加了修饰符 g 返回的是数组
如果没有加 g 返回的是类数组
var str = "hello world, hello duyi, welcome duyi"; var reg = /.ello/; console.log(str.match(reg)); // ['hello', index: 0, input: 'hello world, hello duyi, welcome duyi', groups: undefined]
[
0: "hello" 匹配成功的字符片段
groups: undefined groups代表一个组,这个组代表一个子表达式,没有子表达式就是 undefined
index: 0 当前匹配成功的索引值
input: "hello world, hello duyi, welcome duyi" 我们要匹配的整个字符串
length: 1
]
点 . 不能匹配换行符 \n 和结束符 \r,可以匹配出制表符 \t
var str = "第一行 \nello world, \rello duyi, \tello lizi"; var reg = /.ello/g; console.log(str.match(reg)); // ['\tello']
alert(str) 弹框里面可以看到换行符、回车符的效果分成了三行,制表符的是一个空白
第一行
ello world,
ello duyi, ello lizi
\w
小写 w 代表 26 个大小英文的字母、数字、下划线,
单纯的一个 \w 返回了所有的英文字符,但不包括空格、制表符、换行符、行结束符,逗号
var str = "\rello world, \nello duyi, \tello lizi"; var reg = /\w/g; console.log(str.match(reg)); // ['e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', 'e', 'l', 'l', 'o', 'd', 'u', 'y', 'i', 'e', 'l', 'l', 'o', 'l', 'i', 'z', 'i']
如果想要拆分单词怎么办呢?
可以通过元字符和量词结合的方法,
量词就是元字符的个数,比如 + 加号表示匹配前一个字符的 1 至 多个字符
\w+
元字符 \w 结合量词 +,返回的是字符串中一个一个的单词,去掉了逗号、空格、制表符
var str = "hello world, hello duyi, welcome duyi \tello"; var reg = /\w+/g; console.log(str.match(reg)); // ['hello', 'world', 'hello', 'duyi', 'welcome', 'duyi', 'ello']
正则表达式的规则,一般都会遵循“贪婪匹配”,
就是越多越好,所以量词 + 号是有几个就匹配几个,不是返回单个的字母了
\w*
* 星号代表 0 至 多个,也就是说没有的也能给匹配出来,
匹配出好多个空位,代表 0 个英文字符,还有空逗号、制表符都匹配成空位了
var str = "hello world, hello duyi, welcome duyi \tello"; var reg = /\w*/g; console.log(str.match(reg)); // ['hello', '', 'world', '', '', 'hello', '', 'duyi', '', '', 'welcome', '', 'duyi', '', '', 'ello', '']
\W
大写 W 代表非单词字符,匹配所有的空格、逗号、制表符(就是除了字母、数字、下划线以外的)
var str = "\rello world, \nello \tduyi"; var reg = /\W/g; console.log(str.match(reg)); // ['\r', ' ', ',', ' ', '\n', ' ', '\t']
0: "\r"
1: " "
2: ","
3: " "
4: "\n"
5: " "
6: "\t"
\d
小写 d 代表数字,每一个数字,一个一个的都匹配出来了
var str = "hello world123, hello456 duyi, welcome duyi \tello132323"; var reg = /\d/g; console.log(str.match(reg)); // ['1', '2', '3', '4', '5', '6', '1', '3', '2', '3', '2', '3']
配合量词 + 号,匹配出连着的数字
var str = "hello world123, hello456 duyi, welcome duyi \tello132323"; var reg = /\d+/g; console.log(str.match(reg)); // ['123', '456', '132323']
\D
大写 D 代表非数字,配合量词 + 号,除数字以外的其他字符都匹配出来了
var str = "hello world123, hello456 duyi, welcome duyi \tello132323"; var reg = /\D+/g; console.log(str.match(reg)); // ['hello world', ', hello', ' duyi, welcome duyi \tello']
相当于数字充当了分割符
0: "hello world"
1: ", hello"
2: " duyi, welcome duyi \tello"
\s
小写 \s 表示空白字符,其实就是空格包含 \r、\n、\t
var str = "hello world\r, hello duyi, \nwel comeduyi\t"; var reg = /\s/g; console.log(str.match(reg)); // [' ', '\r', ' ', ' ', ' ', '\n', ' ', '\t'] console.log(str.match(reg).length); // 8
配合量词 + 号,\n 连着前面的空格
var reg = /\s+/g; console.log(str.match(reg)); // [' ', '\r', ' ', ' ', ' \n', ' ', '\t'] console.log(str.match(reg).length); // 7
\S
大写 S 非空白字符,匹配出没有 \r、\n、\t
var str = "hello world, hello duyi,\r welcome \nduyi \tello132323"; var reg = /\S+/g; console.log(str.match(reg)); // ['hello', 'world,', 'hello', 'duyi,', 'welcome', 'duyi', 'ello132323']
\b
匹配单词边界,每一个单词有两个边界,七个单词有14个空白
var str = "hello world, hello duyi,\r welcome \nduyi \tello"; var reg = /\b/g; console.log(str.match(reg)); // ['', '', '', '', '', '', '', '', '', '', '', '', '', '']
单词边界和空格的区别
1. 空格是有字符的
2. 整个字符如果连着 -hello- 左右两边是单词边界,也就是说一个单词有两个边界
\B
非单词边界就是两个挨着的字母之间
var str = "hello world"; var reg = /\B/g; console.log(str.match(reg)); // ['', '', '', '', '', '', '', '']
非单词边界就 h-e-l-l-o 字母之间
var str = "hello"; var reg = /\b/g; console.log(str.replace(reg, '-')); // -hello- var reg = /\B/g; console.log(str.replace(reg, '-')); // h-e-l-l-o
非单词边界有什么用,
详看下面的练习部分“给 10000000000 每三个 0 打一个点变成 10.000.000.000”
四、量词
量词是修饰前面一个字符的个数,就是你想匹配多少个
量词 | 描述 |
n+ | 1次多次 |
n* | 0次1次多次 |
n? | 0次1次 |
n{x} | 前一个字符n固定的个数 |
n{x,y} | 代表一个范围 |
n{x,} | |
n$ | 匹配以n结尾的字符串 |
^n | 任何以n开头的字符串 |
?=n | 正向肯定预查,m(?=n) 匹配任何后面紧接着指定字符串 n 的字符串 |
?!n | 正向否定预查,m(?!n) 匹配后面不是 n 的 m |
?<=n | 反向肯定预查,(?<=n)m 匹配前面是 n 的 m |
?<!n | 反向否定预查,(?<!n)m 匹配前面不是 n 的 m |
上面用到的量词 + 号和 * 号,
都是至多匹配,有多少就拿多少,也就是贪婪匹配的原则
?
问号是至少匹配,只匹配 0 或 1 个,可以取消贪婪匹配
把英文字母一个一个的拿出来,只取字母不要空格,正常的做法是
1. 全局 g 匹配,把全部符合的都匹配出来
2. [A-z] 包括大小写字母
3. 字符串的 match 方法返回一个数组
var str = "hello world"; var reg = /[A-z]/g; console.log(str.match(reg)); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
加上量词 + 号表示 1 次至多次,可以匹配出字符串中的两个单词,
这是正则的贪婪匹配的效果,能匹配多就不匹配少,有多少符合条件的都匹配出来,作为一个字符串
var str = "hello world"; var reg = /[A-z]+/g; console.log(str.match(reg)); // ['hello', 'world']
加上 ? 问号,
表示至少匹配,是最少能拿几个,非贪婪匹配能少就不多,匹配结果又是一个一个的字母了
var str = "hello world"; var reg = /[A-z]+?/g; console.log(str.match(reg)); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
{}
花括号里面只传一个数字,表示的是固定的个数,比如 3 个3个的进行匹配
var str = "hello world"; var reg = /[A-z]{3}/g; console.log(str.match(reg)); // ['hel', 'wor']
2 个字符 2 个字符的进行匹配
var str = "hello world"; var reg = /[A-z]{2}/g; console.log(str.match(reg)); // ['he', 'll', 'wo', 'rl']
如果花括号里面写两个数字,表示的是一个范围,
比如 {2,4} 范围是 2 ~ 4 个之间,贪婪匹配原则有多就不匹配少,4个4个的匹配出来
var str = "hello world"; var reg = /[A-z]{2,4}/g; console.log(str.match(reg)); // ['hell', 'worl']
注意,
两个数字 {2, 4} 之间是逗号隔开,并且不能有空格
var str = "hello world"; var reg = /[A-z]{2, 4}/g; console.log(str.match(reg)); // null
{2, 4} 之间有空格,就把它当字符了,中间就是空格的字符,不是一个范围了
var str = "hello world{2, 4}"; // 把{2, 4}写到这 var reg = /[A-z]{2, 4}/g; console.log(str.match(reg)); // ['d{2, 4}']
把 {2,4} 放到字符里面,有空格就不是范围了,就当做字符匹配了
var str = "hello world{2, 4}"; var reg = /[A-z]{2, 4}/g; console.log(str.match(reg)); // ['d{2, 4}']
[^A-z]
^在方括号里面不代表以某个字符开头了,代表除了中扩号里面以内的其他字符
var str = "hello world{2, 4}"; var reg = /[^A-z]/g; console.log(str.match(reg)); // [' ', '{', '2', ',', ' ', '4', '}']
?=
m(?=n) 正向肯定预查,匹配后面紧跟着 n 的字符串 m
详看下面的练习部分“给 10000000000 每三个 0 打一个点变成 10.000.000.000”
?!
正向否定预查,和正向肯定相对应的,就是后面不跟着某一个字符(正向否定预查用的不是很多),
a(?!d) 我们想匹配的是 a,但条件是 a 后面不能是 d,
修饰符 g 全局匹配出所有的,
字符串里面有三个 a,匹配出后面两个 a
var str = "adkhfalskdfa"; var reg = /a(?!d)/g; console.log(str.match(reg)); // ['a', 'a']
?<=
反向肯定预查, (?<=f)a 我们想匹配 a ,条件是前面是 f 后面的那个 a
var str = "adkhfalskdfa"; var reg = /(?<=f)a/g; console.log(str.match(reg)); // ['a', 'a']
?<!
反向否定预查,(?<!f)a 匹配的是 a,但是 a 的前面不能是 f,所以只有第一个 a 满足条件
var str = "adkhfalskdfa"; var reg = /(?<!f)a/g; console.log(str.match(reg)); // ['a']
注意,
预查必须要加小括号括起来,
但是一定要区分开,
因为我们知道,通过小括号括起来的就是子表达式
预查这里比较特殊,小括号里面是预查的,它就不代表子表达式了
/m(?<!f)a/g
课堂提问,前面加上一个 m,
代表前面是一个 m,
后面的 a 的特点是,前面不跟着 f,
也就是 m 后面不是 f,然后在后面是 a,
预查只是特点,它 (?<!f) 不是匹配的项,
该课堂提问,有点陷进预查了,这样写没有什么意义,直接写 /ma/g 就可以了
五、子表达式
子表达式有很多功能,需要我们去探索,
1、反向引用
提取出三个相同连续重复的字符,比如 aaa、bbb、eee
/\w{3}/ 相当于 /(\w\w\w)/,每个 \w 有自己的范围,它的范围是字母、数字、下划线其中任意的一个字符,最后一个 dde 不符合要求
var str = "aaabbbddeee"; var reg = /\w{3}/g; console.log(str.match(reg)); // ['aaa', 'bbb', 'dde']
(\w)\1
子表达式可以拿到正则表达式中的一部分单独匹配,并将匹配成功的结果在整个正则表示中重复引用
\1 是反向引用,数字 1 是子表达式的编号,代表引用第一个子表达式匹配出来的内容,
就是把子表达式匹配的内容拿出来用,所以匹配的内容跟第一个表达式相同
var str = "aaabbbddeee"; var reg = /(\w)\1/g; console.log(str.match(reg)); // ['aa', 'bb', 'dd', 'ee']
(\w)\1\1
匹配三个相同的字符,就写两个 \1\1 反向引用,
第一个字符是第一个子表达式 (\w)
这两个 \1\1 都是第一个子表达式里面匹配成功的字符
var str = "aaabbbddeee"; var reg = /(\w)\1\1/g; console.log(str.match(reg)); // ['aaa', 'bbb', 'eee']
2、字符串 replace 替换方法
子表达式的“反向引用”在字符串替换方法 replace 里面的应用
1. 参数一传是正则表达式 reg,会把满足正则的位置的字符进行替换
2. 如果参数二传递的是固定的字符串,会把符合匹配规则的部分进行替换
var str = "aaabbbddeee"; var reg = /(\w)\1\1/g; console.log(str.replace(reg, '*')); // **dd*
replace 方法的第二个参数还可以传一个回调函数,
1. 该函数可以接收一些参数,通过打印 arguments 看到函数的形参
2. 函数 return 返回的内容,就是匹配成功的字符,要要替换的新内容
var str = "aaabbbddeee"; var reg = /(\w)\1\1/g; str.replace(reg, function(){ console.log(arguments); }); // Arguments(4) ['aaa', 'a', 0, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ] // Arguments(4) ['bbb', 'b', 3, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ] // Arguments(4) ['eee', 'e', 8, 'aaabbbddeee', callee: ƒ, Symbol(Symbol.iterator): ƒ]
因为匹配成功三次,所以打印了三次,每一次打印的是一个数组
[
0: aaa, 是整个字符串,匹配成功的字符
1: a, 第一个子表达式 (\w),匹配成功的内容
2: 0, 是一个索引值,当前匹配成功的位置
]
传三个形参,分别打印出来
var str = "aaabbbddeee"; var reg = /(\w)\1\1/g; str.replace(reg, function(param1, param2, param3){ console.log(param1, param2, param3); }); // aaa a 0 // bbb b 3 // eee e 8
3、反向引用应用,字符串去重
/(\w)\1+/
(\w) 先匹配一个字母,\1 第二个字母和子表达式匹配的相同,+ 然后可能有很多个这样的字母,只要重复的都匹配出来了
var str = "Aaadddoooooooobbeee"; var reg = /(\w)\1+/gi; console.log(str.match(reg)); // ['Aaa', 'ddd', 'oooooooo', 'bb', 'eee']
接下来就替换重复的字符,
回调函数里面 return 的内容,就是替换的内容,
意思是第二个参数 param2 是子表达式 (\w) 匹配成功的内容,它就一个字符,直接返回第二个参数 param2 就可以了
var str = "Aaadddoooooooobbeee"; var reg = /(\w)\1+/gi; var result = str.replace(reg, function(param1, param2, param3){ return param2; }); console.log(result); // Adobe
去掉修饰符 i 就可以区分大小写了 Aadobe
课堂提问,
如果是两个 /1,替换重复 3 次的字符,
比如中间 8 个字母 o,三个三个的被替换后变成两个o,加上剩下的两个 o,所以结果是四个 o
var str = "Aaadddoooooooobbeee"; var reg = /(\w)\1\1/gi; var result = str.replace(reg, function(param1, param2, param3){ return param2; }); console.log(result); // Adoooobbe
4、replace 方法替换示例,高亮显示
做一个搜索关键词高亮显示效果,
原理就是给第一个参数 param1 加一个高亮样式后返回
正则表达式拼接关键词后是一个字符串,用 RegExp 方式的参数传的是字符串,所以用它定义正则表达式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>搜索关键词高亮</title> <style> </style> </head> <body> <script> var str = '<span style="color:#999">快乐的池塘里面,有一只小青蛙,跳啊跳啊跳</span>'; var pond = '池塘'; var frog = '小青蛙' var jump = '跳'; var keywords = `(${pond}|${frog}|${jump})`; var reg = new RegExp(keywords, 'g'); var result = str.replace(reg, function(param1, param2, param3){ return `<span style="color:#008c8c">${param1}</span>`; }); document.body.innerHTML = result; </script> </body> </html>
六、练习
1、拆分 url
通过子表达式,对整个 url 字符串各个部分,进行依次的匹配
var str = "https://www.baidu.com/s?tn=68018901_3_dg&ie=UTF-8&wd=flash"; var str = "https://www.bilibili.com/video/BV1qpCfY5Eaz/?spm_id_from=333.788.player.player_end_recommend_autoplay&vd_source=30698713e5e2b66f66e6fa017646273c#dsd"; var str = "http://127.0.0.1:8848/js%E6%96%B9%E6%B3%95%E6%95%B4%E7%90%86/text.html"; var reg = /(http|https):\/\/([\w\.]+)(:\d*)?(\/?[\w\/\.%-]*)\??([\w=\.&]+)?#?(.*)?/mig; // console.log(reg.exec(str)); var arr = reg.exec(str); var querys = {}; if(arr[5]){ var _arr = arr[5].split("&"); for(var i = 0; _arr.length > i; i++){ var s = _arr[i].split("="); // console.log(s) querys[s[0]] = s[1]; } } console.log(arr); var obj = { protocol: arr[1], origin: arr[2], port: arr[3], path: arr[4], query: querys }; console.log(obj);
/(http|https):\/\/
协议以 http 或 https 开头,
冒号后面的两个斜线 / 在正则表达式中有特殊含义,和正则表达式起始符 / 重复了,要用反 \ 斜线转义
/(http|https):\/\/([\w\.]+)/
域名规则是由多个字母、点、数字组成,
\w 表示字母和数字
正则表达式里面“点”代表单个字符,除换行和行结束符以外的所有字符,也需要用反斜杠转义
+ 号表示1至多个
/(http|https):\/\/([\w\.]+)(:\d*)?/ 可以不要最后一个?号
端口号由冒号和多个数字组成,
: 冒号可以 0 次 1 或 1 次
\d+ 加号的意思是,1至多个数字,然后 ? 也是 0次 1次
/(http|https):\/\/([\w\.]+)(:\d*)?\/?([\w\/\.%-]*)/
路径可能有英文字符、-、点、中文、斜杠、中文(中文部分转义后有 %),
abc.com/ 域名后面的斜线是路径,有时候默认不显示,所以可以出现 0 次,
路径是多个英文字符,也可能没有,所以用量词 *
/(http|https):\/\/([\w\.]+)(:\d*)?\/?([\w\/\.%-]*)\??([\w=&]+)?/mig
参数部分以 ? 号开头,? 号是量词也需要转义
使用 exec 方法匹配返回的是类数组
[0] 是整个正则表达式匹配成功的内容
[1] 第一个子表达式匹配的内容
[2] 第二个子表达式
[3] ...... 从左往右数,如果有嵌套的小括号,从外往里依次的数
2、给 10000000000 每三个 0 打一个点变成 10.000.000.000(面试题 2 )
我们要匹配的“非单词边界”有一个特点,它后面跟着的是三个数字
先写 \d{3} 代表三个连续的数字 \d\d\d
量词里面有一个“正向预查”?=n
m(?=n) 匹配后面紧跟着 n 的 m,意思是后面的 n 是条件,最后匹配出的是前面的 m。后面的 n 三个数字,前面的 m 是非单词边界
var str = "10000000000"; var reg = /\B(?=\d{3})/; console.log(str.replace(reg, ".")); // 1.0000000000
全局匹配,发现有点不对
var str = "10000000000"; var reg = /\B(?=\d{3})/g; console.log(str.replace(reg, ".")); // 1.0.0.0.0.0.0.0.000
1.0000000000 第一个非单词边界的位置,后面跟着三个数字
1.0.000000000 第二个非单词边界的位置,后面跟着三个数字
1.0.0.00000000 第三个非单词边界的位置,后面跟着三个数字
1.0.0.0.0000000 依次类推
1.0.0.0.0.000000
1.0.0.0.0.0.00000
1.0.0.0.0.0.0.0000
1.0.0.0.0.0.0.0.000 匹配结果
我们需要的是从后往前,每三位数字打一个点
需要加 $ 符号表示从后往前
现在我们匹配的是,以三个数字结尾的单词边界 10000000.000
var str = "10000000000"; var reg = /\B(?=\d{3}$)/g; console.log(str.replace(reg, ".")); // 10000000.000
想再往前面接着每三个数字打一个点,就是3的倍数6
{3} 是量词,+号也是量词,
所以前面的 \d{3} 要加一个小括号和 + 隔开
var str = "10000000000"; var reg = /\B(?=(\d{3})+$)/g; console.log(str.replace(reg, ".")); // 10.000.000.000
(?=..) 问号后面等于/大于/小于的时候,都需要扩上括号
+? 只有问号在量词后面的时候,不需要加括号,代表非贪婪匹配
3、统一空格(面试题 6 )
去掉多余的空格
var str = "Regexp remove string spaces"; var reg = /( )+/g; console.log(str.replace(reg, ' ')); // Regexp remove string spaces
4、把 the-first-name 转换成小驼峰 theFirstName(面试题 4 )
var str = "the-first-name"; // var reg = /(?<=-)\w/gi; var reg = /-\w/gi; var result = str.replace(reg, function(a, b, c){ // console.log(a, b, c); return str[b+1].toUpperCase(); }); console.log(result); // theFirstName
5、附,面试题
1. 正则表达式实现aabb的形式变成bbaaa
2. 给 10000000000 每三个 0 打一个点变成 10.000.000.000
3. 字符串去重 aaaaaaabbbbcccc 变成 abc
4. 把 the-first-name 转换成小驼峰 theFirstName
5. 匹配结尾的数字
6. 统一空格
7. 判断字符串是不是由数字构成
8. 删除字符串中的空格
9. 身份证号匹配
10. 将字符串
"select student.*, result.* from student inner join result on student.id = result.studentid"
和"select * from student"
中的 student 替换成 key 值
刚刚,一个人咳嗽,都已经习以为常了,
不过 2025-05-23 15:17 我字符串处理的能力又提高了,重要的是熟练了,目前比较满意