
刚开始学前端的时候,正则是啥?看到正则,头上好几个问号在转!哈哈哈
其实,正则对于前端工程师来说确实是比较难懂的,但是也确实很简洁,用多了会越来越喜欢。
了解正则的基本用法:正则基础
五一节,跟我弟弟聊了会,了解到之前他应聘某一大型知名互联网公司(顺利拿到offer,目前已入职)的面试中有这样一道面试题。请使用正则表达式实现小数每隔三位加一个逗号。
我思来想去,放弃了。正则感觉确实掌握的不咋滴。然后这段时间回顾了下正则,把基础打牢。
在这里附上答案:
var reg = /(?<=\d)(?=(\d{3})+(\.\d+)?$)/g
var num = '1234567890.12'
num.replace(reg, ',') // '1,234,567,890.12'
嗯~ o( ̄▽ ̄)o 看上去很复杂啊。不急,看完整篇文章,相信你一定能够很好地理解与掌握。
正则用的好,实现奶茶自由不是梦。
正则表达式

在这里,以几个经典的正则案例来深入以上正则的使用。
模式匹配(x)
模式匹配主要是用来匹配某一类字符串并记住匹配项
var reg = /(\w+)\s(\w+)/g
var str = 'theway theway0916'
reg.test(str) // true
str.replace(reg, '$2 $1') // 'theway0916 theway'
解释: 其中 $1 表示第一个被捕获的项,即:theway, $2 表示第二个被捕获的项,即:theway0916。
注意:括号匹配项是无限的, 但是 RegExp 对象能捕获的只有九个. 你可以通过返回一个数组索引来取得所有的括号匹配项
非捕获括号的模式匹配 (?:x)
主要用来匹配某一类字符串但不记住匹配项
var reg = /(?:theway{1,})/g
var str = 'theway theway0916'
reg.test(str) // true
解释: 其中(?:)被称为非捕获括号,我们可以使用它匹配一组字符但是并不记住该字符,一般用来判断某类字符是否存在于某字符串中
先行断言 x(?=y)
匹配 'x' 仅当 'x' 后面紧跟 'y'
var reg = /the(?=way)/g
var str = 'theway'
reg.test(str) // true
解释: /the(?=way)/ 会匹配到 'the' 仅当它后面跟着 'way'。但是 'way' 不属于匹配结果的一部分
后行断言 (?<=y)x
var reg = /(?<=the)way/g
var str = 'theway'
reg.test(str) // true
解释: /(?<=the)way/g 会匹配到 'way' 仅当它前面为 'the',但 'the' 不属于匹配结果的一部分
正向否定查找 x(?!y)
仅仅当 'x' 后面不跟着 'y' 时匹配 'x'
var reg = /\d+(?!\.)/g
var str = '3.141592654'
reg.exec(str) // [141592654]
解释: /\d+(?!.)/g 匹配一个或多个数字,当且仅当它后面没有小数点。所以结果是 141592654,而不是 3.141592654
反向否定查找 (?<!y)x
var reg = /(?<!\.)\d+/g
var str = '3.141592654'
reg.exec(str) // [3]
解释: /(?<!.)\d+/ 匹配一个数字,当且仅当前面字符不是 . 时,此时将匹配 3
字符集合和反向字符集合的用法 [xyz] / [^xyz]
[xyz]: 一个字符集合。匹配方括号中的任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。
[^xyz]: 一个反向字符集。也就是说,它匹配任何没有包含在方括号中的字符。你可以使用破折号(-)来指定一个字符范围。任何普通字符在这里都是起作用的
var str = 'abcd'
var reg1 = /[a-c]+/
var reg2 = /[^d]$/
reg1.test(str) // true
reg2.test(str) // false
解释: 第一个正则将返回true因为字符串中包含a-c中的字符, 第二个正则将返回false, 因为字符串结尾为d, 但正则reg2需要匹配结尾不为d的字符串
词边界和非单词边界匹配 \b\B
\b 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0
\B 匹配一个非单词边界。匹配如下几种情况:(1)字符串第一个字符为非“字”字符 (2)字符串最后一个字符为非“字”字符 (3)两个单词字符之间 (4)两个非单词字符之间 (5)空字符串
var str = 'theway'
var reg1 = /way\b/
var reg2 = /the\B/
reg1.exec(str) // [way]
reg2.exec(str) // [the]
空白字符/非空白字符匹配 \s\S
var str = 'theway is'
var reg1 = /.*\s/
var reg2 = /\S\w*/
reg1.exec(str) // [theway]
reg2.exec(str) // [theway]
解释: 执行之后都将匹配xuxi, 一个是空白字符之前的匹配, 一个是非空白字符的匹配
单字字符/非单字字符匹配 \w\W
\w: 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]
\W: 匹配一个非单字字符。等价于 [^A-Za-z0-9_]
由于以上2种模式比较简单,这里就不一一介绍了
正则实战
- 去除字符串内指定元素的标签
function trimTag(tagName, htmlStr) {
let reg = new RegExp(`<${tagName}(\\s.*)*>(\\n|.)*<\\/${tagName}>`, "g")
return htmlStr.replace(reg, '')
}
- 短横线命名转驼峰命名
// 短横线转驼峰命名, flag = 0为小驼峰, 1为大驼峰
function toCamelCase(str, flag = 0) {
if(flag) {
return str[0].toUpperCase() + str.slice(1).replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
}else {
return str.replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
}
}
- 实现一个简单的模板引擎
关于实现一个模板引擎, 实现中用到了大量的正则,建议感兴趣的可以直接看实现一个简单的模板引擎.
- 去除字符串中的空格符
function trimAll(str) {
return str.replace(/\s*/g,"")
}
- 判断指定格式的数据输入合法性
function numCheck(str, specialNum) {
if(str.indexOf(',') > -1) {
return str.splite(',').every(item=>this.numCheck(item));
} else {
return str.split(specialNum).length === 2;
}
}
- 去除url参数字符串中值为空的字段
// 去除url参数字符串中值为空的字段
const trimParmas = (parmaStr:string = '') => {
return parmaStr.replace(/((\w*?)=&|(&\w*?=)$)/g, '')
}
- 将浏览器参数字符串转化为参数对象
function unParams(params = '?a=1&b=2&c=3') {
let obj = {}
params && params.replace(/((\w*)=([\.a-z0-9A-Z]*)?)?/g, (m,a,b,c) => {
if(b || c) obj[b] = c
})
return obj
}
- 计算字符串字节数
/**
* 计算字符串字节数
* @param str
* @desc 一个中文占2个字节, 一个英文占一个字节
*/
function computeStringByte(str) {
let size = 0,
strArr = str.split(''),
reg = /[\u4e00-\u9fa5]/ // 判断是否为中文
for(let i = strArr.length; i--; i>=0) {
if(reg.test(strArr[i])) {
size+= 2
}else {
size += 1
}
}
return size
}
- 匹配是否包含中文字符
function hasCn(str) {
let reg = /[\u4e00-\u9fa5]/g
return reg.test(str)
}
- 实现搜索联想功能
function searchLink(keyword) {
// 模拟后端返回数据
let list = ['abc', 'ab', 'a', 'bcd', 'edf', 'abd'];
let reg = new RegExp(keyword, 'i');
return list.filter(item => reg.test(item))
}