DIY一个正则匹配引擎

网上看过不少代码的教程,有些按照步骤来一段段代码解读(篇幅会很长),有些会简化代码来讲解,然后逐步扩展(篇幅也会很长),有些干脆直接源代码放出来,在上面注解。
我自己也一直在思考如何把代码讲解这件事表达得更好、更容易理解。
代码的组织其实是个非线性的过程,各种调用穿插,如果按照写文章的逻辑呈现(线性),讲解过程中总会碰到读者突然不明白的情况。
可视化的图解是一个比较好的讲解形态,但是又不适合文章的形态,所以今天我采用了一种,在文章里只讲解构建的原理,着重方法,然后读者带着方法去读源代码(注解过的)。

我们考虑DIY一个正则匹配的引擎,采用JavaScript,为了代码的美观,可维护,我们采用单例模式来编写我们的代码。
class MyRegex { static getInstance(...arg) { if (!MyRegex.instance) MyRegex.instance = new MyRegex(arg); return MyRegex.instance; } constructor() { console.log('运行一次') } test(){}}
使用的时候,是这么调用的:
MyRegex.getInstance().test();
我们接下来只要修改test方法,或者类似于test方法的方式不断地扩展我们的代码就行啦~
- 简化
首先我们把引擎简化下,只考虑匹配一个字符的情况。
编写一个函数matchOne,该函数的输入是一个pattern和一个text,输出是一个布尔值,表示它们是否匹配。
matchOne(pattern, text) { return pattern === text;}
- 递归
递归是非常好的解决方案。我们将要重复调用matchOne。现在,我们要添加对更长长度的pattern和text字符串的支持。同样的,我们需要把问题简化下,暂时让我们仅考虑相同长度的pattern-text对。
match(pattern, text) { return ( this.matchOne(pattern[0], text[0]) && this.match(pattern.slice(1), text.slice(1)) );}
递归函数有个明显特征,函数内部继续调用自身:
function match(){ ... match()}
-考虑各种分支
当我们完成了基本的骨架之后,接下来,要考虑各种情况,比如pattern可能是个空值,text也可能是个空字符串,还有当pattern是特殊字符(比如*?.)等等。
举个例子:
matchOne(pattern, text) {// 当pattern为空的时候,任意文字都是匹配的 if (!pattern) return true; // 当pattern不为空,但是text为空,返回false if (!text) return false; // 当pattern为.时,任意文字都是匹配的 if (pattern === ".") return true; return pattern === text;}
-适当地剥离函数
当函数里的代码过多,或者可以复用的时候,需要把函数剥离出来,让其可读性更强。
match(pattern, text) { if (pattern === "") { return true; } else if (pattern === "$" && text === "") { return true; } else if (pattern[1] === "?") { return this.matchQuestion(pattern, text); } else if (pattern[1] === "*") { return this.matchStar(pattern, text); } else { return ( this.matchOne(pattern[0], text[0]) && this.match(pattern.slice(1), text.slice(1)) ); }}
(0)

相关推荐

  • 提取数字、字母、汉字如此简单

    不啰嗦,直奔主题-- 看看如何提取,一般使用函数提取,难度较大 先看一下数据源: 分别提取数字.字母和汉字 方案1:传统函数公式法 传统的函数方式难度较大,这里只演示一下提取数字,其他不再演示 通用数 ...

  • Python|递归应用

    问题描述在Python的运算中会经常用到递归,下面小编将会用简单的代码做一个解释示例.解决斐波拉数列时我们之前用的是for循环,现在用递归的方法运算,实践一下.解决方案首先用def定义一个函数f(), ...

  • DIY一个以图搜图引擎1

    这位用户一定是位机器学习资深玩家! 吉娃娃和小松糕....的故事,大家应该都看过吧,上面这图也是类似的,有很多长得像脸的食物,以至于让我训练的模型都认为是多个人.. 我还找出了不少的小动物们: 喜欢路 ...

  • 【新提醒】DIY一个DTMB四菱天线,实战接收数字电视地面广播,终于可以免费看电视了!

     本帖最后由 ljlun 于 2020-10-19 09:39  翻箱倒柜,终于找到一条4.5m长的闭路电缆,还是以前撸东西卖家送的                       给天线焊上个母端接头( ...

  • 用电脑鼠标diy 一个发报机自动键

    用电脑鼠标diy一个发报机自动键 CW 所用的电键有 手键和自动键之分.简单说,手键就是一个常开的开关,发信时,短按发出"嘀"声,用"."表示,长按发出&quo ...

  • DIY一个数控开关电源,你需要掌握这些知识

    想要成为一名合格的硬件工程师,熟练掌握电源知识至关重要-- 凡是在工作着的系统都必须要有电源,而电源是否可靠稳定的运行,则影响着整个系统的工作情况.那么,如何产生"干净"的电源?假 ...

  • 5分钟diy一个接收免费数字电视,地面波的简易天线

    本帖最后由 屏论 于 2020-12-9 09:43 编辑 今年全国要关闭模拟电视,各地都开通了免费的地面波,也就是dtmb无线数字电视.正好家里刚刚买了一台新的海信电视机,可以接收无线数字电视,由于 ...

  • python笔记51-re正则匹配findall

    前言 re是python的一个正则匹配库,可以使用正则表达式匹配出我们想要的内容 findall 使用 findall 看下源码介绍, 返回字符串中所有不重叠匹配项的列表. findall匹配的时候, ...

  • python笔记52-re正则匹配search

    前言 re.search扫描整个字符串并返回第一个成功的匹配.re.findall返回字符串中所有不重叠匹配项的列表,如果没有匹配到返回空list不会报错. search匹配对象有3个方法:group ...

  • python笔记54-re正则匹配替换字符串(sub和subn)

    前言 python 里面可以用 replace 实现简单的替换字符串操作,如果要实现复杂一点的替换字符串操作,需用到正则表达式. re.sub用于替换字符串中匹配项,返回一个替换后的字符串,subn方 ...

  • 投影仪太贵?用身边的小工具就能自己在家DIY一个投影仪出来

    投影仪现在已经走进了千家万户,不过我们自己能不能通过身边现有的材料自己做一个投影仪呢,当然答案是肯定的,需要的东西也很简单,一个纸盒.一个放大镜和一个手机. 放大镜的话在文具店可以轻易的买到,小K建议 ...