正则表达式

两种声明方式

*:字面量&&构造函数

const alphabet = '[a-z]';
const reg = new RegExp(`${alphabet}\\d+${alphabet}`, 'i');	//字面量
const reg = /[a-z]\d+[a-z]/i;//字面量

字面量:不易读
构造函数:二次转义会出现问题(需要检查),子内容可以重复使用

const reg = new RegExp(`\d+`);
reg.test('1'); // false
reg.test('ddd'); // true

常用方法

RegExp.prototype.test():输入必须是字符串(隐式转换也可以)

const reg = /[a-z]\d+[a-z]/i;
reg.test('a1a'); // true
reg.test('1a1'); // false
reg.test(Symbol('a1a')); // TypeError

RegExp.prototype.source 和 RegExp.prototype.flags
.source属性,返回两个斜杠之间的内容
.flags返回当前正则表达式的修饰字符串,第二个斜杠外面的内容
RegExp.prototype.exec() 和 String.prototype.match()
关于输入
这里有个转换问题
RegExp.prototype.exec 要求输入字符串,遇到非字符串类型会尝试转换

String.prototype.match 要求输入正则表达式,遇到其它类型会先尝试转成字符串,再以字符串为 source 创建正则表达式
关于输出
当正则表达式含有 g 修饰符时,RegExp.prototype.exec 每次只返回一个匹配结果,数据格式和不含 g 修饰符相同。
String.prototype.match 会返回所有的匹配结果,数据格式会变为字符串数组。
由于 String.prototype.match 返回的数据格式不固定,因此大多数情况都建议使用 RegExp.prototype.exec

//reg.exec(string)
//string.match(exec)
const reg = /[a-z]\d+[a-z]/i;

reg.exec('a1a'); // ["a1a", index: 0, input: "a1a", groups: undefined]
reg.exec('1a1'); // null
'a1a'.match(reg); // ["a1a", index: 0, input: "a1a", groups: undefined]
'1a1'.match(reg); // null

RegExp.prototype.lastIndex
当前正则表达式最后一次匹配成功的结束位置(也就是下一次匹配的开始位置)

const reg = /(a)/g;
const str = 'a1a';

reg.lastIndex; // 0
reg.exec('a1a'); // ["a", "a", index: 0, input: "a1a", groups: undefined]
reg.lastIndex; // 1
reg.exec('a1a'); // ["a", "a", index: 2, input: "a1a", groups: undefined]
reg.lastIndex; // 3
reg.exec('a1a'); // null
reg.lastIndex; // 0

注意: lastIndex 不会自己重置,只有当上一次匹配失败才会重置为 0 ,因此,当你需要反复使用同一个正则表达式的时候,请在每次匹配新的字符串之前重置 lastIndex!
String.prototype.replace()、String.prototype.search()、String.prototype.split()

'a1a'.replace(/a/, 'b'); // 'b1a'
'a1a'.replace(/a/g, 'b'); // 'b1b'

'a1a'.search(/a/); // 0
'a1a'.search(/a/g); // 0

'a1a'.split(/a/); // ["", "1", ""]
'a1a'.split(/a/g); // ["", "1", ""]

正则表达式符号问题

/[0-9]+/:表示0-9之间的数字匹配一个或多个
问题:不一定准确
存在误判,如 /[0-9]+/.test(‘a1’) === true

/[0-9]+/.test('a1') === true	//为什么会误判

/^\d+$/: ^后跟着起始字符,$前跟着结束字符
(Ps:我在markdown里打上面的表达式美元符号也得转义)
Attention:不能匹配带符号的数值,如 +1,-2,不能匹配小数,如 3.14159

/^[+-]?\d+(.\d+)?$/:匹配小数(markdown转义也要=_=)
()圆括号内是一个子表达式,当圆括号不带任何修饰符时,表示同时创建一个捕获组
? 在正则中有多种含义,作为限定符时,表示匹配零到一个
. 可以匹配除换行符之外的任意字符,当结合 s 修饰符时,可以匹配包括换行符在内的任意字符,当匹配小数点字符时需要转义
不能匹配无整数部分的小数,如 .123捕获组会带来额外的开销

/^[+-]?(?:\d.)?\d+$/*
(?: ):创建一个非捕获组
不能匹配无小数部分的数值,如 2.
不能匹配科学计数法,如 1e2、3e-1、-2.e+4
创建一个非捕获组

完整的正则

1. 完整的数值token

/^[+-]?(?:\d+\.?|\d*\.\d+)(?: e[+-]?\d+)?$/i

|: 用来创建分支,当位于圆括号内时,表示子表达式的分支条件,当位于圆括号外时,表示整个正则表达式的分支条件
i 修饰符
表示匹配时忽略大小写,在这个例子中用于匹配科学计数法的 e,去掉 i 修饰符需要把 e 改为 [eE]
思考题:这个正则已经没有缺点了吗?

const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

function execNumberList(str) {
    reg.lastIndex = 0;
    let exec = reg.exec(str);
    const result = [];
    while (exec) {
        result.push(parseFloat(exec[0]));
        exec = reg.exec(str);
    }
    return result;
}

console.log(execNumberList('1.0px .2px -3px +4e1px')); // [1, 0.2, -3, 40]
console.log(execNumberList('+1.0px -0.2px 3e-1px')); // [1, -0.2, 0.3]
console.log(execNumberList('1px 0')); // [1, 0]
console.log(execNumberList('-1e+1px')); // [-10]

修饰符g,表示全局匹配,用于取出目标字符串中所有符合条件的结果
需要注意的点

  • 按照 CSS 规范,只有数值为 0 才可以省略单位,这种情况没有必要靠正则来过滤
  • 这个例子中只验证了 px 单位,实际还存在 pt、em、vw 等单位,并且没有考虑百分比的情况
  • 实际工作中,要根据需求追加处理逻辑
    2. 数值转货币
const reg = /(\d)(?=(\d{3})+(,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$1,');
}

console.log(formatCurrency('1')); // 1
console.log(formatCurrency('123')); // 123
console.log(formatCurrency('12345678')); // 12,345,678

{n}

限定符,表示重复 n 次,n 必须是非负整数
类似的语法还有:
{n, m} 表示重复 n 到 m 次,n 和 m 都必须是非负整数,且 n <= m
{n,} 表示重复 n 次以上

const reg = /\d(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$&,');
}
const reg = /(?<=\d)(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, ',');
}

环视中的圆括号也会生成捕获组,所以都要采用 (?: ) 的非捕获组形式

数值转货币格式

const reg = /(\d)(?=(\d{3})+(,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$1,');
}

console.log(formatCurrency('1')); // 1
console.log(formatCurrency('123')); // 123
console.log(formatCurrency('12345678')); // 12,345,678

$&可以表示本次完整匹配
所以上述例子中,$&和$1是一样的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值