正则表达式的学习与知识点归纳整理

有一个需求就是在一个字符串里面找出数字并返回数组 我们的做法

  1. 循环遍历这个字符串拿到每个字符
  2. 判断每个字符是不是为数组
  3. 用一个临时变量存这个数字
  4. 不是数字了就存到数组里面
 // 需求在字符串中找到数字并存进数组
 let str = "https://www.79bk.cn/"
 function getNumber() {
     // 定义个空数组
     let arr = []
     // 进行拼接使用
     let temp = ""
     // 循环字符串每个字符
     for (let i = 0; i < str.length; i++) {
         // console.log(str[i])
         // 进行判断是否为数字
         if (!isNaN(str[i])) {
             // 是数字就进行拼接
             temp += str[i]
         } else {
             // 不是数字了那么就存到数组
             if (temp != "") {
                 arr.push(temp)
                 //存完了就清空这个拼接所用的变量
                 temp = ""
             }
         }
     }
     // 用于最后是数字的 因为最后是数组 没有不是数字的所以最后要判断下是不是为空
     // 如果有东西就存进去
     if (temp != "") {
     arr.push(temp)
     }
     return arr
 }
 console.log(getNumber())

可以很好进行实现 但是感觉有点繁琐 有没有简单的方法呢?

那么就出现了正则表达式

let str = "https://www.79bk.cn/"
let reg = /\d+/g
let arr = str.match(reg)
console.log(arr)

只需要几行就可以轻松的实现 上面整个函数的功能

正则创建

字面量创建

使用//包裹的字面量创建方式是推荐的作法,但它不能在其中使用变量

let str = "https://www.79bk.cn/"
let reg = /\d+/ //=>创建字面量正则

对象构建函数创建

let str = "https://www.79bk.cn/"
let reg = new RegExp("\\d+") //=>创建对象正则
console.log(str.match(reg))

正则表达式是变动的时候需要使用对象方式创建正则

// 被匹配的字符串
let str = "https://www.79bk.cn/"
// 要匹配的内容
let Retu = "bk"
// 对象进行传入 要匹配的内容 这里是可以变动的
let reg = new RegExp(Retu)
// 如果需要加修饰符 
// let reg = new RegExp(Retu,"g")
// 进行匹配
console.log(str.match(reg))

正则方法

test()

检测是否匹配到东西

可以用于邮箱的验证 也就是说检测你输入的邮箱格式对不对 然后给你返回个 True 和 False

let str = "https://www.79bk.cn/"
//匹配数字
let req = /\d+/ 
console.log(req.test(str))//=> True
// 将字符串的数字删除
let str = "https://www.bk.cn/"
console.log(req.test(str))//=> False

exce()

不使用 g 修饰符时与 match 方法使用相似,使用 g 修饰符后可以循环调用直到全部匹配完。

let str = "https://www.79bk.cn/52179"
//匹配数字
let req = /\d+/ 
//第一次 
console.log(req.exec(str))//=> 79
//第二次 
console.log(req.exec(str))//=> 52179

字符串方法

split()

用于使用字符串或正则表达式分隔字符串

let str = "https://www.79bk.cn/"
let arr = str.split("/")
console.log(arr)
//==> ["https:", "", "www.79bk.cn", ""]

replace()

replace 方法不仅可以执行基本字符替换,也可以进行正则替换,

let str = "https://www.79bk.cn/"
let reg = /\d+/g
let res = str.replace(reg, "*")
console.log(res)
// => https://www.*bk.cn/

问题:我的是两个数字 79 理想应该是 ** 两个星号

replace 支持回调函数操作,用于处理复杂的替换逻辑

let str = "https://www.79bk.cn/"
let reg = /\d+/g
let res = str.replace(reg, function (arg) {
        return "*".repeat(arg.length)
})
console.log(res)
// => https://www.**bk.cn/

这样结果就符合意思了

用于检索字符串中指定的子字符串,也可以使用正则表达式搜索,返回值为索引位置,如果找不到就返回 -1

let str = "https://www.79bk.cn/"
let res = str.search(/\d+/)
console.log(res) //=> 12

match()

let str = "https://www.79bk.cn/"
let res = str.match(/\d+/)
console.log(res)
//=>["79", index: 12, input: "https://www.79bk.cn/", groups: undefined]

如果使用 g 修饰符时,就不会有结果的详细信息了(可以使用exec)

let res = str.match(/\d+/g)
console.log(res)
// => ["79"]

元字符

选择符

| 这个符号带表选择修释符,也就是 | 左右两侧有一个匹配到就可以。

检测是否包含 qy 或者 79

const hd = "www.79bk.cn";
console.log(/qy|79/.test(hd)); //true

字符转义

转义用于改变字符的含义,用来对某个字符有多种语义时的处理。

假如有这样的场景,如果我们想通过正则查找/符号,但是 /在正则中有特殊的意义。如果写成///这会造成解析错误,所以要使用转义语法 / \/ /来匹配。

const url = "https://www.79bk.cn";
console.log(/https:\/\//.test(url)); //true

子字符

元字符 说明 示例
\d 匹配任意一个数字 [0-9]
\D 与除了数字以外的任何一个字符匹配 [^0-9]
\w 与任意一个英文字母,数字或下划线匹配 [a-zA-Z_]
\W 除了字母,数字或下划线外与任何字符匹配 [^a-zA-Z_]
\s 任意一个空白字符匹配,如空格,制表符\t,换行符\n [\n\f\r\t\v]
\S 除了空白符外任意一个字符匹配 [^\n\f\r\t\v]
. 匹配除换行符外的任意字符

匹配任意数字 \d

let str = "www.79bk.cn";
console.log(str.match(/\d/g)); //["7", "9"]

匹配任意非数字 \D

let str = "www.79bk.cn";
console.log(str.match(/\D/g)); //["w", "w", "w", ".", "b", "k", ".", "c", "n"]

匹配字母数字下划线 \w

let str = "_blog@79bk.com";
console.log(str.match(/\w/g)); //["_", "b", "l", "o", "g", "7", "9", "b", "k", "c", "o", "m"]

匹配除了字母,数字或下划线外与任何字符匹配 \W

let str = "_blog@79bk.com";
console.log(str.match(/\W/g)); //["@", "."]

匹配与任意一个空白字符匹配 \s

console.lg(/\s/.test(" ")); //true
console.log(/\s/.test("\n")); //true

匹配除了空白符外任意一个字符匹配 \S

let str = "_blo g@79bk .co m";
console.log(str.match(/\S/g));
//=> ["_", "b", "l", "o", "g", "@", "7", "9", "b", "k", ".", "c", "o", "m"]

模式修饰

修饰符 说明
i 不区分大小写字母的匹配
g 全局搜索所有匹配内容
m 视为多行
s 视为单行忽略换行符,使用. 可以匹配所有字符
y regexp.lastIndex 开始匹配
u 正确处理四个字符的 UTF-16 编码

i

let str = "79bk.cn 79BK.CN";
str = str.replace(/79bk\.cn/gi, "79bk.cn");
console.log(str);

g

使用 g 修饰符可以全局操作内容

let str = "79bkblog";
str = str.replace(/b/, "@");
console.log(str); //没有使用 g 修饰符是,只替换了第一个
// => 79@kblog

使用g

let str = "79bkblog";
str = str.replace(/b/g, "@");
console.log(str); //使用全局修饰符后替换了全部的b
// => 79@k@log

字符集合

在一组字符中匹配某个元字符,在正则表达式中通过元字符表来完成,就是放到[] (方括号)中。

原子表 说明
[] 只匹配其中的一个原子
[^] 只匹配”除了”其中字符的任意一个原子
[0-9] 匹配0-9任何一个数字
[a-z] 匹配小写a-z任何一个字母
[A-Z] 匹配大写A-Z任何一个字母

获取0~3间的任意数字

let num = "2";
console.log(/[0-3]/.test(num)); //true

注意:

let num = "123564,2534,7652"
let reg = /[0-23]+/g
let res = num.replace(reg, "*")
console.log(res) //=>*564,*5*4,765*

只会替换掉 0,2,3

匹配a~f间的任意字符

let hd = "e";
console.log(/[a-f]/.test(hd)); //true

边界符

使用字符边界符用于控制匹配内容的开始与结束约定。

^

匹配内容必须以www开始

let url = "www.79bk.cn";
console.log(/^www/.test(url)); //true

$

匹配内容必须以.cn结束

let url = "www.79bk.cn";
console.log(/\.com$/.test(url)); //true

分组

{} 可以指定出现的次数

let str = "qianduanbokeshi79bkhhnizhendeehaohao"
// let reg = /hh/g
let reg = /h{2}/g
let res = str.replace(reg, "*")
console.log(res)

新需求我们想将ha进行替换

let str = "qianduanbokeshi79bkhhnizhendeehaohao"
let reg = /hao{2}/g
let res = str.replace(reg, "*")
console.log(res)
//=> qianduanbokeshi79bkhhnizhendeehaohao

很显然这样是不可以替换的

我们这时候就需要使用分组了 ()

let str = "qianduanbokeshi79bkhhnizhendeehaohao"
let reg = /(hao){2}/g
let res = str.replace(reg, "*")
console.log(res)
//=> qianduanbokeshi79bkhhnizhendee*

小演示

let str = "My name is LiLei"
//将 LiLei 替换成 李雷
let reg = /LiL|lei/g;
let res = str.replace(reg, "李雷")
console.log(res) //=> My name is 李雷ei

想要的结果是不对的 这时候用上 ()分组

let str = "My name is LiLei"
//将 LiLei 替换成 李雷
let reg = /Li(L|l)ei/g;
let res = str.replace(reg, "李雷")
console.log(res) //=> My name is 李雷

这时候不管lei 还是Lei 都可以正常替换

对时间进行格式转换

let mytime = "2020-09-23"
let reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g
let res = mytime.replace(reg,"$1/$2/$3")
console.log(res) //=> 2020/09/23

$1就代表reg里面的第一个分组 以此类推

分组别名

如果希望返回的组数据更清晰,可以为分组编号 结果将保存在返回的 groups字段中

组别名使用 ?<> 形式定义

let url = "<h1>79bk.cn</h1>";
console.log(url.match(/<(?<tag>h[1-6])[\s\S]*<\/\1>/));

零宽断言

分为 正向(后面) 和 负向(前面) 又 分为 肯定断言 和 否定断言

let str = "iphone4iphone5iphone6iphone11iphone12iphoneNumber"
//将 iphone 替换成苹果
let reg = /iphone\d{1,2}/g
let res = str.replace(reg, "苹果")
console.log(res)
//=> 苹果苹果苹果苹果苹果iphoneNumber

结果并不是我们想要的结果 而且 4 5 6 11 12 这些数字丢失了

那么我们可以用正向断言进行解决

(?=exp)

零宽先行断言 ?=exp 匹配后面为 exp 的内容

let str = "iphone4iphone5iphone6iphone11iphone12iphoneNumber"
//将 iphone 替换成苹果
let reg = /iphone(?=\d{1,2})/g
let res = str.replace(reg, "苹果")
console.log(res)
//=>苹果4苹果5苹果6苹果11苹果12iphoneNumber

(?!exp)

let str = "iphone4iphone5iphone6iphone11iphone12iphoneNumber"
//将 iphone 替换成苹果
let reg = /iphone(?!\d{1,2})/g
let res = str.replace(reg, "苹果")
console.log(res)
//=> iphone4iphone5iphone6iphone11iphone12苹果Number

(?<=exp)

零宽后行断言 ?<=exp 匹配前面为 exp 的内容

let str = "1px2px3px4px44pxipx"
//px --> 像素
let reg = /(?<=\d{1,2})px/g
let res = str.replace(reg, "像素")
console.log(res)
//=> 1像素2像素3像素4像素44像素ipx

(?<!exp)

let str = "1px2px3px4px44pxipx"
//px --> 像素
let reg = /(?<!\d{1,2})px/g
let res = str.replace(reg, "像素")
console.log(res)
//=> 1px2px3px4px44pxi像素
上一篇

Node.js模块Fs文件操作模块的学习