【JavaScript】正则表达式

转义符 \

转义字符是字符的一种间接表示方式。在特殊语境中,无法直接使用字符自身

  • eg:想用单引号包裹单引号,可以使用 \'
let str = '你非常\'优秀\'';
console.log(str); // 你非常'优秀'
  • 如果想显示转义符 \,可以写 \\
let str = '你非常\\优秀\\';
console.log(str); // 你非常\优秀\
  • 一些规定好的转义字符:\n 换行符、\t 水平制表符、\r 回车符…

正则

  • 正则表达式是字符串的一种匹配模式,说白了就是检索字符串中特定字符的规则

创建正则

① 使用构造函数创建:let reg = new RegExp();
  • JS 提供了一个内置构造函数 RegExp() (regular expression),用来创建正则表达式

    接收 2 个参数:① 正则的规则、② 修饰符 i m g

let reg = new RegExp('test'); // 实例化一个正则对象
console.log(reg); // /test/
② 使用简洁语法创建:let reg = /正则规则/修饰符;
let reg = /text/;
console.log(reg); // /test/
  • 一般情况下,推荐使用简洁语法创建

    但对于字符串变量,只能使用构造函数创建

let str = 'text';
let reg1 = /str/; // /str/
let reg2 = new RegExp(str); // /text/

修饰符

  • i:不区分大小写 (ignoreCase)
  • m:换行匹配 (multiline)
  • g:全局匹配 (global)

使用简洁语法创建正则时,修饰符跟在最后;使用构造函数创建正则时,修饰符作为第二参数

i:不区分大小写 (ignoreCase)

默认区分大小写,设置 i 后不区分大小写

let reg = /Text/;
let str = 'This is a text';
console.log(str.match(reg)); // null - 返回 null 表示匹配失败
let reg = /Text/i; // 不区分大小写
let str = 'This is a text';
console.log(str.match(reg)); // [ 'text', index: 10, input: 'This is a text', groups: undefined ]
m:换行匹配 (multiLine)

默认是单行匹配,设置 m 后能换行匹配

let reg = new RegExp('^Text'); // 检查字符串前缀是否为 Test
let str = 'This is a \nText and';
console.log(str.match(reg)); // null - 返回 null 表示匹配失败
let reg = new RegExp('^Text', 'm'); // 换行匹配
let str = 'This is a \nText and';
console.log(str.match(reg)); // [ 'Text', index: 11, input: 'This is a \nText and', groups: undefined ]
g:全局匹配 (global)

默认只匹配一个,设置 g 能匹配多个

let reg = new RegExp('text');
let str = 'This is a text and text and text';
console.log(str.match(reg)); // ["text", index: 10, input: "This is a text and text and text", groups: undefined]
let reg = new RegExp('text', 'g');
let str = 'This is a text and text and text';
console.log(str.match(reg)); // ["text", "text", "text"]

正则的方法

  • 正则表达式 reg 调用方法
  • 传入的参数是字符串 str
test():用于判断参数 str 中是否含有匹配正则的子字符串
  • 返回值:含有匹配正则的子字符串则返回 true;否则返回 false
// demo: 匹配 ^a
let reg1 = /^a/g; // ^ 有特殊意义
let reg2 = /\^a/g; // 匹配 ^ 需要使用转义符 \ 转义
let str = 'bb^acc';
console.log(reg1.test(str)); // false - 匹配失败
console.log(reg2.test(str)); // true - 匹配成功
exec():获取第 1 个匹配正则的子字符串的信息
  • 返回一个数组,存放匹配正则的子字符串的信息;如果没有找到匹配的子字符串,则返回 null
let reg1 = /superman/;
let reg2 = /monster/;
let str = 'hello superman';
console.log(reg1.exec(str)); // [ 'superman', index: 6, input: 'hello superman', groups: undefined ]
console.log(reg2.exec(str)); // null
  • 匹配正则的子字符串的信息包括:子字符串、开始下标、字符串 str、所在分组

字符串的方法

  • 字符串 str 调用方法
  • 传入的参数是正则表达式 reg
match():获取所有匹配正则的子字符串组成的数组 / 获取第 1 个匹配正则的子字符串的信息
  1. 如果 reg 没有设置全局修饰符 g:获取第 1 个匹配正则的子字符串的信息
let reg1 = /superman/;
let reg2 = /monster/;
let str = 'hello superman';
console.log(str.match(reg1)); // [ 'superman', index: 6, input: 'hello superman', groups: undefined ]
console.log(str.match(reg2)); // null
  1. 如果 reg 有设置全局修饰符 g:获取所有匹配正则的子字符串组成的数组
let reg1 = /superman/g;
let reg2 = /monster/g;
let str = 'hello superman';
console.log(str.match(reg1)); // [ 'superman' ]
console.log(str.match(reg2)); // null
search():获取第 1 个匹配正则的子字符串的开始下标
let reg = /superman/;
let str = 'hello superman';
console.log(str.search(reg)); // 6
split():以匹配正则的子字符串为分界点,把字符串转成数组
let reg = /superman/;
let str = 'hello superman superman aaa';
console.log(str.split(reg)); // [ 'hello ', ' ', ' aaa' ]
replace():找到匹配正则的子字符串,用第 2 参数将其替换
let reg1 = /man/; // 替换匹配正则的第 1 个子字符串
let reg2 = /man/g; // 替换匹配正则的所有子字符串
let str = 'hello superman superman';
console.log(str.replace(reg1, 'women')); // hello superwomen superman
console.log(str.replace(reg2, 'women')); // hello superwomen superwomen

特殊语法

特殊字符
  • 正则表达式 = 普通字符 + 特殊字符
  • 普通字符:字母(abcABC)、数字(123)、_$
    特殊字符:\[]{}()^$*?+|.
  • 普通字符可以直接使用(上面的例子都是使用普通字符)
    如果要匹配特殊字符,得使用转义符 \ 修饰,因为特殊字符在正则中有特殊意义
// 匹配 ^a
let reg = /\^a/g; // ^ 有特殊意义,匹配 ^ 需要使用转义符 \ 转义
let str = 'bb^acc';
console.log(str.match(reg)) // [ '^a' ]
预定义的特殊字符:\t 水平制表符、\n 换行符、\f 换页符、\b 退格符…

界定符

检查前后缀
  • 检查前缀用 ^,如:/^abc/ 检查字符串的前缀是否为 abc
  • 检查后缀用 $,如:/xyz$/ 检查字符串的后缀是否为 xyz
let str = 'sdf';
let reg = /^s/;
console.log(reg.test(str)); // true
检查其后是否紧跟着指定字符串
  • (?=n):匹配到后面紧跟着字符 n 的字符串
  • (?!n):匹配到后面没有紧跟着字符 n 的字符串
let str = 'abcd';
let reg = /bc(?=d)/g; // 找到后面跟着 d 的字符串 bc
console.log(str.match(reg)); // [ 'bc' ]

字符集 []

简单类
  • 通过 [] 包裹住,来表示这几个字母组成的一个简单集合
    如:[abDF45] 表示由 abDF45 6 个字符组成的一个集合
// 在 `str` 中找到第 1 个在集合 `[gbk]` 中的字符
let str = 'abcdefg';
let reg = /[gbk]/g;
console.log(str.match(reg)); // [ 'b', 'g' ]
范围类
  • 通过 [小字符-大字符] 组成的一个范围集合(大小指的是 ASCII 码大小)
    如:[a-z] 表示小写字母集合、[A-Z] 表示大写字母集合、[0-9] 表示数字集合
let str = 'abcdefg';
let reg = /[f-i]/g;
console.log(str.match(reg)); // [ 'f', 'g' ]
  • 要按照字符编码集从小到大写 eg:[A-z];不能从大到小写 eg:[a-Z]
  • 特殊的字符集:[\u4e00-\u9fa5] 表示中文集
负向类
  • [^字符] 内部添加 ^ 前缀,表示不包含该集合的字符集
    如:[^abc] 表示不包含 abc 的集合,[^ab89CD] 表示不包含 ab89CD 这 6 个字符的集合
let str = 'abcdef';
let reg = /[^abc]/g;
console.log(str.match(reg)); // [ 'd', 'e', 'f' ]
组合类
  • 将几个集合拼接在一起,表示一个组合的集合
    如:[a-zA-Z0-9] 表示大小写字母以及数字的集合
let str = '0';
let reg = /[0-9a-z]/;
console.log(reg.test(str)); // true
注意:在 [] 内,无论写多少个字符,只会匹配其中一个

元字符

就是特殊的转义字符,把一些字母转成特殊意义的字符

  • .[^\n\r]:除了换行和回车之外的任意字符
  • \d[0-9]:数字字符( digit 数字 )
  • \D[^0-9]:非数字字符
  • \s[\t\n\f\r]:空白字符
  • \S[^\t\n\f\r]:非空白字符
  • \w[a-zA-Z_0-9]:字母数字下划线
  • \W[^a-zA-Z_0-9]:非字母数字下划线
let str = 'sdf';
let reg = /\W/;
console.log(reg.test(str)); // false

量词 {}

  • 用于设置匹配的字符个数

  • 默认贪婪匹配,即尽量往字符个数多的匹配;在量词后加 ?,则变为惰性匹配,即尽量往字符个数少的匹配

  • 重复书写某个规则时,可以用量词代替。eg:匹配 10 个数字,/\d\d\d\d\d\d\d\d\d\d//\d{10}/

普通写法
  • {n}:n 个
  • {n,m}:n ~ m 个,闭区间 [n, m](注意:n,m, 后面不要空格)
  • {n,}:n ~ 无数个,半开半闭区间 [n, ∞)
let str = 'a b a bb a bbb a bbbb';

let reg1 = /b{2,4}/g; // 贪婪匹配
console.log(str.match(reg1)); // ["bb", "bbb", "bbbb"]

let reg2 = /b{2,4}?/g; // 惰性匹配
console.log(str.match(reg2)); // ["bb", "bb", "bb", "bb"]
特殊写法
  • {0,1}?
  • {0,}*
  • {1,}+
let str = 'babba'; // 5 个字符

let reg1 = /b?/g;
console.log(str.match(reg1)); // [ 'b', '', 'b', 'b', '', '' ] → 6 个元素,按匹配元素分割开了

let reg2 = /b*/g;
console.log(str.match(reg2)); // [ 'b', '', 'bb', '', '' ] → 5 个元素,也是按匹配元素分割开了

let reg3 = /b+/g;
console.log(str.match(reg3)); // ["b", "bb"]

子项 ()

可以用 () 将部分正则括住,这样在使用 match / exec 做匹配时,能获取指定字符开头的数据

let str = "abcd12ef";
let reg = /d(\d+)/g; // 获取 d 开头的数字字符串
console.log(str.match(reg)); // [ 'd12' ]
子项的反引用

格式:\numnum 为子项的序号

let str = "ccsdbbcc99d";
let reg = /([a-z])\1/g; // 获取 XX 格式的子字母字符串
console.log(str.match(reg)); // [ 'cc', 'bb', 'cc' ]

上面 \1 表示复用第 1 个子项 ([a-z]) 的结果

获取 |

在正则中,| 表示或者
let str = "adcd12ef";
let reg = /ad|cd/g;
console.log(str.match(reg)); // [ 'ad', 'cd' ]

可以与子项结合使用:

let str = "adcd12ef";
let reg = /(a|c)d/g;
console.log(str.match(reg)); // [ 'ad', 'cd' ]
在字符集中,| 是普通的竖线
let str = "adcd1|d2ef";
let reg = /[a|c]d/g; // `[a|c]` 表示 `a`、`|`、`b` 中的任意 1 个
console.log(str.match(reg)); // [ 'ad', 'cd', '|d' ]

demo

demo 1:手机号( 11 位数字、第一位是 1 )
let reg = /^1\d{10}$/;
let num = 13188886666;
if (reg.test(num)) {
    console.log('成功');
} else {
    console.log('失败');
}
demo 2:QQ 邮箱
let eMail = /^\d{6-10}@q{2}\.com$/;

. 在正则中有特殊意义,所以需要转义

demo 3:日期格式转换
function formatDate(date, fmt) {
    // 年
    let reg = /Y+/;
    if (reg.test(fmt)) {
        let str = fmt.match(reg)[0]; // 获取年份的格式
        // 使用 str.substring(start, end) 控制年份的表示长度与格式一致
        let year = (date.getFullYear() + '').substring(4 - str.length);
        fmt = fmt.replace(str, year); // 用年份替换格式字符串
    }

    // 月日时分秒
    let obj = {
        'M+': date.getMonth() + 1,
        'D+': date.getDate(),
        'h+': date.getHours(),
        'm+': date.getMinutes(),
        's+': date.getSeconds()
    }

    for (let key in obj) {
        let reg = new RegExp(key);
        if (reg.test(fmt)) {
            let str = fmt.match(reg)[0]; // 获取对应时间的格式
            fmt = fmt.replace(str, toTwo(obj[key])); // 用时间替换格式字符串
        }
    }

    return fmt;
}

function toTwo(num) {
    return (num > 10 ? '' : '0') + num;
}

let date = new Date();
let fmt = 'YYYY-MM-DD hh:mm:ss';
console.log(formatDate(date, fmt));
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值