数字千分位分割、手机号3-3-4格式拼接、trim函数实现、HTML转义、获取url query参数...你是不是也经常在面试和工作中遇到呢?让我们一起看看,如何用正则将他们一网打尽吧!!!
❝将123456789变成123,456,789
❞
这道题估计大家在面试和工作中也经常遇到,出现频率比较高。
'123456789'.replace(/(?!^)(?=(\d{3})+$)/g, ',') // 123,456,789
题目意思大概是:
1 . 从后往前每三个数字
前加一个逗号
2 . 开头不能加逗号(比如:123
最后不能变成,123
)
是不是很符合(?=p)的规律呢?p可以表示每三个数字,要添加的逗号所处的位置正好是(?=p)匹配出来的位置。
「第一步,尝试先把后面第一个逗号弄出来」
let price = '123456789'
let priceReg = /(?=\d{3}$)/
console.log(price.replace(proceReg, ',')) // 123456,789
「第二步,把所有的逗号都弄出来」
要把所有的逗号都弄出来,主要要解决的问题是怎么表示三个数字一组
,也就是3的倍数。我们知道正则中括号可以把一个p模式变成一个小整体,所以利用括号的特性,可以这样写
let price = '123456789'
let priceReg = /(?=(\d{3})+$)/g
console.log(price.replace(priceReg, ',')) // ,123,456,789
「第三步,去掉首位的逗号,」
上面已经基本上实现需求了,但是还不够,首位还会出现逗号,那怎么把首位的逗号去除呢?想想是不是有一个知识正好满足这个场景?没错(?!p),就是他了,两者结合就是从后往前每三个数字的位置前添加逗号,但是这个位置不能是^首位。
let price = '123456789'
let priceReg = /(?!^)(?=(\d{3})+$)/g
console.log(price.replace(priceReg, ',')) // 123,456,789
❝将手机号18379836654转化为183-7983-6654
❞
表单搜集场景,经常遇到的手机格式化
let mobile = '18379836654'
let mobileReg = /(?=(\d{4})+$)/g
console.log(mobile.replace(mobileReg, '-')) // 183-7983-6654
有了上面数字的千分位分割法,做这个题相信会简单很多,也就是从后往前找到这样的位置:
每四个数字前的位置,并把这个位置替换为-
let mobile = '18379836654'
let mobileReg = /(?=(\d{4})+$)/g
console.log(mobile.replace(mobileReg, '-')) // 183-7983-6654
❝将手机号18379836654转化为183-7983-6654 需要满足以下条件
❞
想想这其实是我们经常遇到的用户输入手机号的过程中,需要不断格式化。
const formatMobile = (mobile) => {
return String(mobile).slice(0,11)
.replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
.replace(/(?<=[\d-]{8})\d{1,4}/, ($0) => '-' + $0)
}
console.log(formatMobile(18379836654))
这里用(?=p)就不太合适了,例如1234就会变成-1234。我们需要另寻他法, 正则中还有其他的知识点方便处理这种场景吗?有 (?<=p)
「第一步, 将第一个-弄出来」
const formatMobile = (mobile) => {
return String(mobile).replace(/(?<=\d{3})\d+/, '-')
}
console.log(formatMobile(123)) // 123
console.log(formatMobile(1234)) // 123-4
「将第二个-弄出来」
接着我们弄出来第二个,第二个-正好处于第8位(1234567-)的位置。
const formatMobile = (mobile) => {
return String(mobile).slice(0,11)
.replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
.replace(/(?<=[\d-]{8})\d{1,4}/, ($0) => '-' + $0)
}
console.log(formatMobile(123)) // 123
console.log(formatMobile(1234)) // 123-4
console.log(formatMobile(12345)) // 123-45
console.log(formatMobile(123456)) // 123-456
console.log(formatMobile(1234567)) // 123-4567
console.log(formatMobile(12345678)) // 123-4567-8
console.log(formatMobile(123456789)) // 123-4567-89
console.log(formatMobile(12345678911)) // 123-4567-8911
❝密码长度是6-12位,由数字、小写字母和大写字母组成,但必须至少包括2种字符
❞
let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z])^[a-zA-Z\d]{6,12}$/
console.log(reg.test('123456')) // false
console.log(reg.test('aaaaaa')) // false
console.log(reg.test('AAAAAAA')) // false
console.log(reg.test('1a1a1a')) // true
console.log(reg.test('1A1A1A')) // true
console.log(reg.test('aAaAaA')) // true
console.log(reg.test('1aA1aA1aA')) // true
题目由三个条件组成
「第一步,写出条件1和2和正则」
let reg = /^[a-zA-Z\d]{6,12}$/
「第二步,必须包含某种字符(数字、小写字母、大写字母)」
let reg = /(?=.*\d)/
// 这个正则的意思是,匹配的是一个位置
// 这个位置需要满足`任意数量的符号,紧跟着是个数字`,
// 注意它最终得到的是个位置而不是其他的东西
// (?=.*\d)经常用来做条件限制
console.log(reg.test('hello')) // false
console.log(reg.test('hello1')) // true
console.log(reg.test('hel2lo')) // true
// 其他类型同理
「第三步,写出完整的正则」
必须包含两种字符,有下面四种排列组合方式
// 表示条件1和2
// let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))/
// 表示条件条件3
// let reg = /(?=.*[a-z])(?=.*[A-Z])/
// 表示条件123
// let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z])/
// 表示题目所有条件
let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z])^[a-zA-Z\d]{6,12}$/
console.log(reg.test('123456')) // false
console.log(reg.test('aaaaaa')) // false
console.log(reg.test('AAAAAAA')) // false
console.log(reg.test('1a1a1a')) // true
console.log(reg.test('1A1A1A')) // true
console.log(reg.test('aAaAaA')) // true
console.log(reg.test('1aA1aA1aA')) // true
❝将有重复的字符提取出来,例如12323454545666,提取[ '23', '45', '6' ]
❞
const collectRepeatStr = (str) => {
let repeatStrs = []
const repeatRe = /(.+)\1+/g
str.replace(repeatRe, ($0, $1) => {
$1 && repeatStrs.push($1)
})
return repeatStrs
}
题目中有几个关键信息是
那什么是连续重复呢?
11是连续重复、22也是连续重复、111当然也是。也就是说某些字符X之后一定也是跟着X,就叫连续重复。如果很明确知道X是就是1,那么/11+/
也就可以匹配了,但关键是这里的X是不明确的,怎么办呢?。
使用反向引用
的正则知识可以很方便解决这个问题。
「第一步,写出表示有一个字符重复的正则」
// 这里的X可用.来表示,即所有的字符,并用括号进行引用,紧跟着反向应用\1,也就是体现了连续重复的意思啦
let repeatRe = /(.)\1/
console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('123')) // true
「第二步,写出表示有n个字符重复的正则」
因为并不确定是要匹配11还是45``45
所以括号内需要用量词+来体现n个重复字符,而反向引用本身也可以是大于一个的,例如 45``45``45
let repeatRe = /(.+)\1+/
console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('454545')) // true
console.log(repeatRe.test('124')) // false
「第三步,提取所有连续重复的字符」
const collectRepeatStr = (str) => {
let repeatStrs = []
const repeatRe = /(.+)\1+/g
// 很多时候replace并不是用来做替换,而是做数据提取用
str.replace(repeatRe, ($0, $1) => {
$1 && repeatStrs.push($1)
})
return repeatStrs
}
console.log(collectRepeatStr('11')) // ["1"]
console.log(collectRepeatStr('12323')) // ["23"]
console.log(collectRepeatStr('12323454545666')) // ["23", "45", "6"]
❝去除字符串的首尾空格
❞
// 去除空格法
const trim = (str) => {
return str.replace(/^\s*|\s*$/g, '')
}
// 提取非空格法
const trim = (str) => {
return str.replace(/^\s*(.*?)\s*$/g, '$1')
}
初看题目我们脑海中闪过的做法是把空格部分删除掉,保留非空格的部分
,但是也可以换一种思路,也可以把非空格的部分提取出来,不管空格的部分。接下来我们来写一下两种trim方法的实现
「方式一、去除空格法」
const trim = (str) => {
return str.replace(/^\s*|\s*$/g, '')
}
console.log(trim(' 前端胖头鱼')) // 前端胖头鱼
console.log(trim('前端胖头鱼 ')) // 前端胖头鱼
console.log(trim(' 前端胖头鱼 ')) // 前端胖头鱼
console.log(trim(' 前端 胖头鱼 ')) // 前端 胖头鱼
「方式二、提取非空格法」
const trim = (str) => {
return str.replace(/^\s*(.*?)\s*$/g, '$1')
}
console.log(trim(' 前端胖头鱼')) // 前端胖头鱼
console.log(trim('前端胖头鱼 ')) // 前端胖头鱼
console.log(trim(' 前端胖头鱼 ')) // 前端胖头鱼
console.log(trim(' 前端 胖头鱼 ')) // 前端 胖头鱼
❝防止XSS攻击的方式之一就是做HTML转义,转义规则如下,要求将对应字符转换成等值的实体。而反转义则是将转义后的实体转换为对应的字符
❞
字符 | 转义后的实体 |
---|---|
& | & |
< | < |
> | > |
" | " |
' | ' |
const escape = (string) => {
const escapeMaps = {
'&': 'amp',
'<': 'lt',
'>': 'gt',
'"': 'quot',
"'": '#39'
}
const escapeRegexp = new RegExp(`[${Object.keys(escapeMaps).join('')}]`, 'g')
return string.replace(escapeRegexp, (match) => `&${escapeMaps[match]};`)
}
全局匹配&
、<
、>
、"
、'
,将其按照上述表格替换就可以。类似这种某个字符可能是多种情况之一的时候,我们一般会使用字符组
来做 即[&<>"']
const escape = (string) => {
const escapeMaps = {
'&': 'amp',
'<': 'lt',
'>': 'gt',
'"': 'quot',
"'": '#39'
}
// 这里和/[&<>"']/g的效果是一样的
const escapeRegexp = new RegExp(`[${Object.keys(escapeMaps).join('')}]`, 'g')
return string.replace(escapeRegexp, (match) => `&${escapeMaps[match]};`)
}
console.log(escape(`
<div>
<p>hello world</p>
</div>
`))
/*
<div>
<p>hello world</p>
</div>
*/
反转义也就是刚才的逆过程,我们很容易写出
const unescape = (string) => {
const unescapeMaps = {
'amp': '&',
'lt': '<',
'gt': '>',
'quot': '"',
'#39': "'"
}
const unescapeRegexp = /&([^;]+);/g
return string.replace(unescapeRegexp, (match, unescapeKey) => {
return unescapeMaps[ unescapeKey ] || match
})
}
console.log(unescape(`
<div>
<p>hello world</p>
</div>
`))
/*
<div>
<p>hello world</p>
</div>
*/
❝如下规则,将对应字符串变成驼峰写法
❞
1. foo Bar => fooBar
2. foo-bar---- => fooBar
3. foo_bar__ => fooBar
const camelCase = (string) => {
const camelCaseRegex = /[-_\s]+(.)?/g
return string.replace(camelCaseRegex, (match, char) => {
return char ? char.toUpperCase() : ''
})
}
分析题目的规律
-``空格``_
如(Foo
、--foo
、__FOO
、_BAR
、Bar
)-``空格``_
后面有可能不跟任何东西 如(__
、--
)const camelCase = (string) => {
// 注意(.)?这里的?是为了满足条件2
const camelCaseRegex = /[-_\s]+(.)?/g
return string.replace(camelCaseRegex, (match, char) => {
return char ? char.toUpperCase() : ''
})
}
console.log(camelCase('foo Bar')) // fooBar
console.log(camelCase('foo-bar--')) // fooBar
console.log(camelCase('foo_bar__')) // fooBar
❝例如 hello world 转为为Hello World
❞
const capitalize = (string) => {
const capitalizeRegex = /(?:^|\s+)\w/g
return string.toLowerCase().replace(capitalizeRegex, (match) => match.toUpperCase())
}
找到单词的首字母然后将其转化为大写字母就可以,单词前面可能是开头
也可能是多个空格
。
const capitalize = (string) => {
const capitalizeRegex = /(?:^|\s+)\w/g
return string.toLowerCase().replace(capitalizeRegex, (match) => match.toUpperCase())
}
console.log(capitalize('hello world')) // Hello World
console.log(capitalize('hello WORLD')) // Hello World
❝要求必须是在线链接 例如
https://xxx.juejin.com/a.jpg
、http://xxx.juejin.com/a.jpg
、//xxx.juejjin.com/a.jpg
❞
平时写过一些爬虫的同学对匹配img标签的url一定不陌生,为了准确抓取小姐姐的图片地址,一定动用了你各种聪明才智,最后也如愿以偿。
题目中限定了
img
接下来我们直接看结果,通过可视化的形式看一下这个正则要表示的意思是啥
const matchImgs = (sHtml) => {
const imgUrlRegex = /<img[^>]+src="((?:https?:)?\/\/[^"]+)"[^>]*?>/gi
let matchImgUrls = []
sHtml.replace(imgUrlRegex, (match, $1) => {
$1 && matchImgUrls.push($1)
})
return matchImgUrls
}
我们把正则分成几个部分来看
2.1 (?:https?:)? 表示支持协议头为http:或者https:
2.2 括号外面的?,表示可以没有协议头,即支持//xxx.juejjin.com/a.jpg
形式的链接
2.3 接着是两个斜线
2.4 因为src="" 双引号内的部分即为链接,所以[^"]+
表示除了"其他部分都行
3. 接着就是"到img结束标签>之间的部分了,除了>之外,啥都可以 [^>]*?
「试试结果」
我们到知乎,打开控制台,可以看到是符合预期的。
const getQueryByName = (name) => {
const queryNameRegex = new RegExp(`[?&]${name}=([^&]*)(&|$)`)
const queryNameMatch = window.location.search.match(queryNameRegex)
// 一般都会通过decodeURIComponent解码处理
return queryNameMatch ? decodeURIComponent(queryNameMatch[1]) : ''
}
url query上的参数 name=前端胖头鱼
所处的位置可能是
紧跟着问号
?name=前端胖头鱼&sex=boy在最后的位置
?sex=boy&name=前端胖头鱼在1和2之间
?sex=boy&name=前端胖头鱼&age=100所以只要处理三个地方基本就可以通过正则来取了
const getQueryByName = (name) => {
const queryNameRegex = new RegExp(`[?&]${name}=([^&]*)(?:&|$)`)
const queryNameMatch = window.location.search.match(queryNameRegex)
// 一般都会通过decodeURIComponent解码处理
return queryNameMatch ? decodeURIComponent(queryNameMatch[1]) : ''
}
// 1. name在最前面
// https://juejin.cn/?name=前端胖头鱼&sex=boy
console.log(getQueryByName('name')) // 前端胖头鱼
// 2. name在最后
// https://juejin.cn/?sex=boy&name=前端胖头鱼
console.log(getQueryByName('name')) // 前端胖头鱼
// 2. name在中间
// https://juejin.cn/?sex=boy&name=前端胖头鱼&age=100
console.log(getQueryByName('name')) // 前端胖头鱼
❝判断时间time是否符合24小时制 要求可以匹配规则如下
❞
01:14
1:14
1:1
23:59
const check24TimeRegexp = /^(?:(?:0?|1)\d|2[0-3]):(?:0?|[1-5])\d$/
24小时制的时间的时
和分
分别需要满足
「时」
2.1 当第一位是01时,第二位可以是任意数字
2.2 当第二位是2时,第二位只能是0、1、2、3
「分」
「第一步,先写出符合1和4规则的正则」
const check24TimeRegexp = /^(?:[01]\d|2[0-3]):[0-5]\d$/
console.log(check24TimeRegexp.test('01:14')) // true
console.log(check24TimeRegexp.test('23:59')) // true
console.log(check24TimeRegexp.test('23:60')) // false
console.log(check24TimeRegexp.test('1:14')) // false 实际需要支持
console.log(check24TimeRegexp.test('1:1')) // false 实际需要支持
「第二步,写出时和分都可以是单数的情况」
const check24TimeRegexp = /^(?:(?:0?|1)\d|2[0-3]):(?:0?|[1-5])\d$/
console.log(check24TimeRegexp.test('01:14')) // true
console.log(check24TimeRegexp.test('23:59')) // true
console.log(check24TimeRegexp.test('23:60')) // false
console.log(check24TimeRegexp.test('1:14')) // true
console.log(check24TimeRegexp.test('1:1')) // true
❝要求匹配(yyyy-mm-dd、yyyy.mm.dd、yyyy/mm/dd),例如
2021-08-22
、2021.08.22
、2021/08/22
可以不考虑平闰年❞
const checkDateRegexp = /^\d{4}([-\.\/])(?:0[1-9]|1[0-2])\1(?:0[1-9]|[12]\d|3[01])$/
「日期格式主要分为三个部分」
yyyy年部分
这部分只要是四个数字就可以\d{4}
mm月份部分
2.1 一年只有12个月,前10个月可以用0\d
2.2 10月份及其以后以后 1[0-2]
3. dd日部分
3.1 一个月最多是31日
3.2 最小是1号
「分隔符」
需要注意的是分割符必须一样不能-./三种混用,比如2021.08-22
根据以上分析我们可以写出
const checkDateRegexp = /^\d{4}([-\.\/])(?:0[1-9]|1[0-2])\1(?:0[1-9]|[12]\d|3[01])$/
console.log(checkDateRegexp.test('2021-08-22')) // true
console.log(checkDateRegexp.test('2021/08/22')) // true
console.log(checkDateRegexp.test('2021.08.22')) // true
console.log(checkDateRegexp.test('2021.08/22')) // false
console.log(checkDateRegexp.test('2021/08-22')) // false
可视化形式中有一个Backref #1 ,也就是反向引用第一个分组也就 ([-\.\/])
、这样就保证了分割符一定是一样的
❝要求从字符串string中匹配类似
#ffbbad
、#FFF
16进制颜色值❞
const matchColorRegex = /#(?:[\da-zA-Z]{6}|[\da-zA-Z]{3})/g
16进制的颜色值由以下两部分组成
#
数字
、大小写字母
组成const matchColorRegex = /#(?:[\da-zA-Z]{6}|[\da-zA-Z]{3})/g
const colorString = '#12f3a1 #ffBabd #FFF #123 #586'
console.log(colorString.match(matchColorRegex))
// [ '#12f3a1', '#ffBabd', '#FFF', '#123', '#586' ]
我们不能把正则写成/#(?:[\da-zA-Z]{3}|[\da-zA-Z]{6})/g
,因为正则中的多选分支|是惰性匹配的,优先匹配前面的分支,这时候去匹配'#12f3a1 #ffBabd #FFF #123 #586'
,将会得到[ '#12f', '#ffB', '#FFF', '#123', '#586' ]
❝检查一个url是否是http或者https协议头
❞
这个相对简单,但是在日常工作中还是经常碰到。
const checkProtocol = /^https?:/
console.log(checkProtocol.test('https://juejin.cn/')) // true
console.log(checkProtocol.test('http://juejin.cn/')) // true
console.log(checkProtocol.test('//juejin.cn/')) // false
❝检测字符串str是否是都由中文组成
❞
最重要是要确定中文在unicode的编码范围汉字 Unicode 编码范围,如果要加上基本汉字之外的匹配,只需要用多选分支即可
const checkChineseRegex = /^[\u4E00-\u9FA5]+$/
console.log(checkChineseRegex.test('前端胖头鱼'))
console.log(checkChineseRegex.test('1前端胖头鱼'))
console.log(checkChineseRegex.test('前端胖头鱼2'))
❝检测一个字符串是否符合手机号的规则
❞
「时效性」
手机号本身是有时效性的,各大运营商有时候会推出新的号码,所以我们的正则也具有时效性,需要及时补充
「规律性」
具体规律可以查看 中国大陆移动终端通信号码
正则参考自 ChinaMobilePhoneNumberRegex
const mobileRegex = /^(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[235-8]\d{2}|4(?:0\d|1[0-2]|9\d))|9[0-35-9]\d{2}|66\d{2})\d{6}$/
console.log(mobileRegex.test('18379867725'))
console.log(mobileRegex.test('123456789101'))
console.log(mobileRegex.test('+8618379867725'))
console.log(mobileRegex.test('8618379867725'))
当遇到一个很长看起来很复杂的正则的时候,有什么好办法可以让我们看懂它?
「可以借助可视化工具辅助我们拆解正则。」
所以mobileRegex可以分成以下几个部分
(?:\+?86)?
: 手机前缀,括号内通过?:
标识非引用分组拆解开来后会发现其实也不复杂,只是第三部分因为可能性太多了,用了好多多选分支来说明,只要理清楚了手机号规则,每个分组里面的规律也就不难了。
❝字母汉字组成的字符串,用正则给英文单词加前后空格。如:
you说来是come,去是go
=>you 说来是 come ,去是 go
例子❞
这里只要了解正则中\b
位置的概念就可以了,\b
的意思是单词的边界,具体讲有三点规则
所以:
第一个单词you
,符合规则2、
第二个单词come,符合规则1、
第三个单词符合go,符合规则3
const wordRegex = /\b/g
console.log('you说来是come,去是go'.replace(/\b/g, ' ')) // ` you 说来是 come ,去是 go `
❝将字符串大小写取反,例如hello WORLD => HELLO world
❞
这题比较容易想到的是通过ASCII码确定大小写,然后再转成对应的值即可,但是既然是正则的总结,我们就尝试一下通过正则来完成。
不通过ASCII码那如何确定一个字符是否是大写呢?其实只要将他变成了大写字符,再与元字符比较一下,相等那说明远字符也是大写的。比如
对于字符串 x = `A`
'A'.toUpperCase()得到的y是A
y === x
那么x就是大写字符
所以题目可以这样写
const stringCaseReverseReg = /[a-z]/ig
const string = 'hello WORLD'
const string2 = string.replace(stringCaseReverseReg, (char) => {
const upperStr = char.toUpperCase()
// 大写转小写,小写转大写
return upperStr === char ? char.toLowerCase() : upperStr
})
console.log(string2) // HELLO world
文件
夹和文件路径❝要求匹配如下路径
❞
const windowsPathRegex = /^[a-zA-Z]:\\(?:[^\\:*<>|"?\r\n/]+\\?)*(?:(?:[^\\:*<>|"?\r\n/]+)\.\w+)?$/;
windows下的文件规则大概由这几部分构成
磁盘符:\文件夹\文件夹\文件
[a-zA_Z]:\\
([^\\:*<>|"?\r\n/]+\\?)*
([^\\:*<>|"?\r\n/]+)\.\w+
,但是文件可以没有const windowsPathRegex = /^[a-zA-Z]:\\(?:[^\\:*<>|"?\r\n/]+\\?)*(?:(?:[^\\:*<>|"?\r\n/]+)\.\w+)?$/;
console.log( windowsPathRegex.test("C:\\Documents\\Newsletters\\Summer2018.pdf") ); // true
console.log( windowsPathRegex.test("C:\\Documents\Newsletters\\") ); // true
console.log( windowsPathRegex.test("C:\\Documents\Newsletters") ); // true
console.log( windowsPathRegex.test("C:\\") ); // true
❝要求
<div id="box">hello world</div>
中的id box❞
const matchIdRegexp = /id="([^"]*)"/
console.log(`
<div id="box">
hello world
</div>
`.match(matchIdRegexp)[1])
写爬虫的过程中经常需要匹配指定条件的dom元素,然后再去做对应的操作。那么怎么获取box呢
<div id="box">
hello world
</div>
相信大家最先想到的是这个正则id="(.*)"
const matchIdRegexp = /id="(.*)"/
console.log(`
<div id="box">
hello world
</div>
`.match(matchIdRegexp)[1])
但是id="(.*)"
很容易导致回溯,从而耗费更多的匹配时间。有什么优化的方式吗?
是的只需要将.
换成[^"]
即可,当遇到"时,正则即认为匹配结束,也就不会发生回溯了。
const matchIdRegexp = /id="([^"]*)"/
console.log(`
<div id="box">
hello world
</div>
`.match(matchIdRegexp)[1])
❝我们试试能不能批量获取id
❞
const idRegexp = /id="([^"]+)"/g
document.body.innerHTML
.match(idRegexp)
.map((idStr) => idStr.replace(idRegexp, '$1'))
const pointRegex = /^(?:[1-9]?\d|1[0-4]\d)$/
我们可以将这道题分成两部分看
1 . 整数部分 a . 个位整数 b . 十位整数 c . 百位整数但小于150
2 . 小数部分:只能是.5
或者没有
「先尝试写整数部分」
// 1. 如何表示个位数? /\d/
// 2. 如何表示十位数? /[1-9]\d/
// 3. 个位和十位如何一起表示? /[1-9]?\d/
// 4. 小于150的百位数呢? /1[0-4]\d/
// 所以结合起来整数部分可以用以下正则表示
const pointRegex = /^(?:[1-9]?\d|1[0-4]\d)$/
console.log(pointRegex.test(0)) // true
console.log(pointRegex.test(10)) // true
console.log(pointRegex.test(100)) // true
console.log(pointRegex.test(110.5)) // false
console.log(pointRegex.test(150)) // false
「再加上小数部分」
// 小数部分相对简单 /(?:\.5)?/,所以整体结合起来就是
const pointRegex = /^(?:[1-9]?\d|1[0-4]\d)(?:\.5)?$/
console.log(pointRegex.test(0))
console.log(pointRegex.test(10))
console.log(pointRegex.test(100))
console.log(pointRegex.test(110.5))
console.log(pointRegex.test(150))
❝要求版本号必须是X.Y.Z格式,其中XYZ都是至少一位的数字
❞
// x.y.z
const versionRegexp = /^(?:\d+\.){2}\d+$/
console.log(versionRegexp.test('1.1.1'))
console.log(versionRegexp.test('1.000.1'))
console.log(versionRegexp.test('1.000.1.1'))
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/RYb2Jlse8tbwUuINbRDlmw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。