博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
再议 js 数字格式之正则表达式
阅读量:6909 次
发布时间:2019-06-27

本文共 2046 字,大约阅读时间需要 6 分钟。

前面我们提到到了js的数字格式《》,之前的《》里也提到了优化数字匹配的正则。
不过最近落叶给了我一个正则,让我豁然开朗,比我写的犀利多了,所以今天拿出来简单说一下(只说十进制部分的匹配)。

先看下我之前写的正则:/\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?/

落叶在 jQuery 中发现的正则: /(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ (ps: 我去掉了 [+-] 因为没必要匹配那个。。)
很明显犀利很多。

我的思路其实很简单,就是根据官方描述然后写了个臃肿不堪的正则。

在 MDN 的 一节中可以看到。
对于js数字格式的语法描述为 [(+|-)][digits][.digits][(E|e)[(+|-)]digits] (PS:这不是正则)
所以我就粗略的写了一个表达式 (?:\d+)?(?:\.\d+)?(?:[eE][+-]?\d+)?
当时看着比较舒服,但是在测试中,我发现了严重的问题,能空匹配,简单说就是任何空字符串都能匹配成功。
这是一个严重的BUG,所以我把它拆分为两部分,修复了这个BUG,于是得到了上面那个臃肿的代码,没办法水平有限。
其实是我想的太简单了,我只是按照传统的想法写的正则,先匹配整数,然后匹配小数,最后匹配指数。。。

再看 jQuery 中的正则 /(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ 写的太霸气了。

他的思路是先匹配浮点数,然后匹配小数点后面的整数,接着匹配指数,同样是3部分,只是匹配顺序不同而已。
当然如果匹配不到浮点数,就回溯放弃匹配,直接匹配整数和指数部分。
这样就不需要拆分成两个表达式了。

我们做个测试,先去掉 | 试试,测试数据如下:

1231.231.2e31.2e+31.2e-3.123.12e3.12e+3.12e-3

正则: /(?:\d*\.)\d+(?:[eE][+-]?\d+|)/

发现 123 没匹配到,后面的浮点型数据都可以正常匹配。

为什么会这样呢,因为 (?:\d*\.) 是必须匹配到 . 的,所以整数就无法匹配成功了。
(?:\d*\.|) 则可以在匹配失败的情况下回溯然后发现第二个表达式是个空,就是不匹配了。
自然就让出位置给后面的 \d+ 进行匹配了,所以整数可以匹配成功。

这个正则霸气在于利用最少的代码实现最优的性能,当然整数情况回溯是必须的,不过性能上也不会有多大的问题。

我们来看个测试吧:

var str1 = "123, 1.23, 1.2e3, 1.2e+3, 1.2e-3, .123, .12e3, .12e+3, .12e-3";var str2 = "123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123";var re1 = /\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?/g;var re11= new RegExp(re1.source, "g");var re2 = /(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/g;var re22= new RegExp(re2.source, "g");console.log(    str1.match(re1).toString() === str1.match(re22).toString(),    str2.match(re1).toString() === str2.match(re22).toString());test(str1, re1, "str1 re1")(str1, re11, "str1 re11")    (str1, re2, "str1 re2")(str1, re22, "str1 re22");test(str2, re1, "str2 re1")(str2, re11, "str2 re11")    (str2, re2, "str2 re2")(str2, re22, "str2 re22");function test(str, re, name) {    console.time(name);    for (var i=0; i<1e6; ++i) str1.match(re);    console.timeEnd(name);    return test;}

对浮点和整数进行100万次匹配测试,可以看到浮点数测试相差0.1秒,整数相差0.2秒。
这已经是非常小的性能差异了,有的垃圾正则,100万次测试可能会相差十几甚至几十秒呢。

这么个小知识点让我开拓了眼界,其实只是写的少,看的少,所以一直都是井底蛙,技术这东西,必须多看,多想,多写才行。

好了今天的分享完毕,明天见。

转载地址:http://noycl.baihongyu.com/

你可能感兴趣的文章
matlab骨架曲线,从滞回曲线提取骨架曲线点Matlab程序
查看>>
php教程制作验证码,php生成验证码_PHP教程
查看>>
mysql 提取重复列,将mysql中的行转换为列以获取自定义值[重复]
查看>>
matlab中概率函数,Matlab概率函数大全
查看>>
matlab进行fft模块,Matlab 进行FFT
查看>>
matlab 计算逆时针夹角,求取向量A逆时针到向量B的夹角
查看>>
java怎么查看线程id,Java 获取线程id
查看>>
zblog+php+免费企业主题,ZblogPHP主题:Company企业双语自适应
查看>>
matlab中如何标注%3c=,Matlab数据读取(文本、二进制等).doc
查看>>
检查django是否安装mysql,django 配置mysql流程以及运行报错的解决
查看>>
2020年最新JAVA考试题库,精选2020年JAVASE综合完整考试题库188题(含参考答案)
查看>>
php redis 缓存实例,php 使用 redis 的缓存实例
查看>>
jq注册信息发送php后台,10行JQ搞定短信验证码发送
查看>>
oracle颜色,oracle-apex - APEX更改IG中的行颜色 - SO中文参考 - www.soinside.com
查看>>
oracle为什么有个11g,oracle 11g 体系结构研究
查看>>
oracle system用户创建job 其他用户,oracle中创建用户、角色、权限、表空间简单使用...
查看>>
oracle gather_stats_job,Oracle经验分享:GATHER_STATS_JOB 任务
查看>>
linux用tab分割字符串,[awk] 用-F指定多分隔符及正则表达式
查看>>
linux中怎么删除端口占用,Linux中解除端口占用的方法
查看>>
linux加密压缩文件命令,linux 系统下 zip 的加密压缩与解压缩命令
查看>>