# 正则表达式

正则表达式是用于匹配字符串中字符组合的模式,在 JavaScript中,正则表达式也是对象。

与普通函数操作字符串来比较,正则表达式可以写出更简洁、功能强大的代码。

# 创建正则

JS提供字面量与对象两种方式创建正则表达式

# 字面量创建

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

let web = "jc-sir.github.io";
console.log(/u/.test(web));//true

下面尝试使用 a 变量时将不可以查询

let web = "jc-sir.github.io";
let a = 'u';
console.log(/a/.test(web));//true

虽然可以使用 eval 转换为js语法来实现将变量解析到正则中,但是比较麻烦,所以有变量时建议使用下面的对象创建方式

let web = "jc-sir.github.io";
let a = 'u';
console.log(eval(`/${a}/`).test(web));//true

# 对象创建

当正则需要动态创建时使用对象方式

let web = "jc-sir.github.io";
let subStr = "sir";
let reg = new RegExp(subStr);
console.log(reg.test(web)); //true

# 选择符

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

判断字符串中是否含有test或者jcsir

var str = "test the regExp!";
console.log(/test|jcsir/.test(str))  // true

# 字符转义

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

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

const url = "http://jc-sir.githuo.io";
// 是否有'http://'
console.log(/http:\/\//.test(url)); //true

使用 RegExp 构建正则时在转义上会有些区别,下面是对象与字面量定义正则时区别

let price = 12.23;
//含义1: .   除换行外任何字符 	含义2: .普通点
//含义1: d   字母d   			含义2: \d 数字 0~9
console.log(/\d+\.\d+/.test(price));

//字符串中 \d 与 d 是一样的,所以在 new RegExp 时\d 即为 d
console.log("\d" == "d");

//使用对象定义正则时,可以先把字符串打印一样,结果是字面量一样的定义就对了
console.log("\\d+\\.\\d+");
let reg = new RegExp("\\d+\\.\\d+");
console.log(reg.test(price));

# 字符边界

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

边界符号 说明
^ 匹配字符串的开始
$ 匹配字符串的结束,忽略换行符

示例

匹配内容必须以www开始

var url = "www.jc-sir.github.io"
console.log(/^www/.test(url))  //true

匹配内容必须以 .io 结束

console.log(/.io$/.test(url))  //true

检测用户名长度为3~6位,且只能为字母。如果不使用 ^与$ 限制将得不到正确结果

let reg = /^[a-z]{3,6}$/i
console.log(reg.test("sjkfds"));  // true
console.log(reg.test("sjkfd1ds"));  // false

# 元子字符

元字符是正则表达式中的最小元素,只代表单一(1个)字符

元字符 说明 示例
\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]
. 匹配除换行符外的任意字符

# 使用示例

匹配任意数字

let test = "This is 2020";
console.log(test.match(/\d/g)); //["2", "0", "2", "0"]

 // + 代表匹配一个或者多个
console.log(test.match(/\d+/g)); //["2020"]

let test = "This is 20 20";
console.log(test.match(/\d{1,2}/g)); //["20", "20"]

匹配任意非数字

console.log(/\D/.test(2029)); //false

console.log('this is 2020'.match(/\D+/g)); // ["this is "]

匹配所有电话号码

let tel = `张三:010-99999999,李四:020-88888888`;
let res = tel.match(/\d{3}-\d{7,8}/g);
console.log(res);  //["010-99999999", "020-88888888"]

匹配字母数字下划线

let regstr = "this is jc-sir.github.io_";
console.log(regstr.match(/\w+/g)); 
// ["this", "is", "jc", "sir", "github", "io_"]

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

let regstr = "this is jc-sir.github.io_";
console.log(regstr.match(/\W+/g));
//  [" ", " ", "-", ".", "."]

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

console.log(/\s/.test(" ")); //true
console.log(/\s/.test("\n")); //true
console.log(/\s/.test("\f")); //true
console.log(/\s/.test("\r")); //true
console.log(/\s/.test("\t")); //true
console.log(/\s/.test("\v")); //true

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

let web = "this js-sir.github.io  ";
console.log(web.match(/\S+/g));
// ["this", "js-sir.github.io"]

如果要匹配点则需要转义

因为. 匹配除换行符外的任意字符

let baidu = "www.baidu@com"
console.log(/baidu.com/i.test(baidu)); //true
console.log(/baidu\.com/i.test(baidu)); //false
// 因为换行符  后面的将被忽略
let url = `
  https://www.baidu.com
  jc-sir.githu.io
`;
console.log(url.match(/.+/)[0]);  //https://www.baidu.com

使用 /s视为单行模式(忽略换行)时,. 可以匹配所有

正则中空格会按普通字符对待

let url = `
  https://www.baidu.com
  jc-sir.githu.io
`;
let reg = url.match(/./s);
console.log(reg[0])
// https://www.baidu.com
// jc-sir.githu.io

# 所有字符

可以使用 [\s\S] 或 [\d\D] 来匹配所有字符

# 模式修饰

正则表达式在执行时会按他们的默认执行方式进行,但有时候默认的处理方式总不能满足我们的需求,所以可以使用模式修正符更改默认方式。

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

# i

不区分大小写

let Str = "This Is My blog";
let reg = /i/gi;
console.log(Str.match(reg));  // [i,I]

let reg = /i/g;
console.log(Str.match(reg));  // [i]

// 替换成小写
console.log(Str.replace(reg,"i"));
// This is my blog

# g

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

不使用则匹配到第一个将停止继续匹配

# m

用于将内容视为多行匹配,主要是对 ^和 $ 的修饰

示例

将下面是将以 #数字开始的编程语言解析为对象结构

let proStr = `
  #1 js,前端 #
  #2 php,后端 #
  #9 java,后端 # 最牛逼的编程语言
  #3 css, 前端#
`;
 let regExp = /^\s+#\d\s+.+\s+#$/gm;

let language = proStr.match(regExp).map(v=>{
    v = v.replace(/\s*#\d+\s*/,"").replace(/\s+#/,"");
    [name,type] = v.split(",");
    return {name,type};
})
console.log(JSON.stringify(language,null,2));

// 执行结果
[
  {
    "name": "js",
    "type": "前端"
  },
  {
    "name": "php",
    "type": "后端"
  }
]

# u

每个字符都有属性,如 L 属性表示是字母,P 表示标点符号,需要结合 u 模式才有效

//使用\p{L}属性匹配字母
let blog = "Jc-sir.github.io.个人博客!";
console.log(blog.match(/\p{L}+/gu));
// ["Jc", "sir", "github", "io", "个人博客"]

//使用\p{P}属性匹配标点
console.log(blog.match(/\p{P}+/gu));
// ["-", ".", ".", ".", "!"]

字符也有unicode文字系统属性 Script=文字系统,下面是使用 \p{sc=Han} 获取中文字符 han为中文系统.

let blog = "博客,Jc-sir.github.io.个人博客!";

let res = blog.match(/\p{sc=Han}+/gu);
console.log(res)
// ["博客","个人博客"]

使用 u 模式可以正确处理四个字符的 UTF-16字节编码

let str = "𝒳𝒴";
console.table(str.match(/[𝒳𝒴]/)); //结果为乱字符"�"

console.table(str.match(/[𝒳𝒴]/u)); //结果正确 "𝒳"

# lastIndex

RegExp对象lastIndex 属性可以返回或者设置正则表达式开始匹配的位置

  • 必须结合 g 修饰符使用
  • 对 exec 方法有效
  • 匹配完成时,lastIndex 会被重置为0
let blog = "我的博客地址:jc-sir.github.io";
let reg = /\p{sc=Han}/gu;
while ((res = reg.exec(blog))) {
  console.log(res[0]);
}
// 控制台看结果

# y

使用y模式后如果从 lastIndex 开始匹配不成功就不继续匹配了

let blog = "jc-sir.github.io sir";
let reg = /sir/y;
reg.lastIndex = 3;
console.log(reg.exec(blog));
console.log(reg.lastIndex); // 6
console.log(reg.exec(blog)); // null
console.log(reg.lastIndex); // 0

# 原子表

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

# 使用语法

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

# 使用示例

使用 [] 匹配其中任意字符即成功

let blog = "this is my blog!";
console.log(/mg/.test(blog));  // false
console.log(/[mg]/.test(blog)) // true

匹配日期格式 -或者/

let date = "2022-02-23";
console.log(date.match(/\d{4}([-\/])\d{2}\1\d{2}/));

区间内数字匹配

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

匹配a~f间的任意字符

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

顺序为升序否则将报错

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

字母也要升序否则也报错

const blog = "jc-sir.github.io";
console.log(/[f-a]/.test(blog)); //SyntaxError

获取所有用户名

let str = `
张三:010-99999999,李四:020-88888888`;
let reg = /[^:\d-,\n]+/g;

console.log(str.match(reg)); // ["张三", "李四"]

原子表中有些正则字符不需要转义,如果转义也是没问题的,可以理解为在原子表中. 就是小数点

let str = "(jc-sir.github.io)+";
console.table(str.match(/[().+]/g));

//使用转义也没有问题
console.table(str.match(/[\(\)\.\+]/g));

# 原子组

  • 原子组与原子表的差别在于原子组一次匹配多个元子,而原子表则是匹配任意一个字符。
  • 元字符组用 () 包裹
Last Updated: 9/7/2020, 10:59:05 PM