28

DIY一个正则匹配引擎

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzA3MDgyMjMwMA%3D%3D&%3Bmid=2649937202&%3Bidx=1&%3Bsn=a8415e5b8ff29f8d15743d3984fcbf54
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

网上看过不少代码的教程,有些按照步骤来一段段代码解读 (篇幅会很长) ,有些会简化代码来讲解,然后逐步扩展 (篇幅也会很长) ,有些干脆直接源代码放出来,在上面注解。

我自己也一直在思考如何把代码讲解这件事表达得更好、更容易理解。

代码的组织其实是个 非线性 的过程,各种调用穿插,如果按照写文章的逻辑呈现 (线性) ,讲解过程中总会碰到读者突然不明白的情况。

可视化的图解 是一个比较好的讲解形态,但是又不适合文章的形态,所以今天我采用了一种, 在文章里只讲解构建的原理,着重方法,然后读者带着方法去读源代码 (注解过的)

NniEjyf.png!web

我们考虑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))

);

}

}

详细的我们可以直接阅读代码了解 (阅读原文)

相关推荐

设计模式

超用户预期?AR+多屏协同的技术与体验

shadow的实验记录

shadow的实验记录 ,主要记录一些 智能产品架构相关的知识跟经验 ,比如智能设计、智能写作、短视频技术、代码上的设计模式,一些前沿的产品, 人工智能技术的实践经验,人机交互设计的思考 商业化的思考 全栈开发技术、设计方法论 还有在做的一些 实验、workshop ,提供 答疑、咨询

AJnUR3A.jpg!web

欢迎跟我交流


Recommend

  • 70
    • 掘金 juejin.im 6 years ago
    • Cache

    教科书式的正则匹配

    前言 正则在js中是一类比较特殊的对象,它可以匹配各个场景需要的格式验证,例如邮箱、手机号、用户登录名、密码等等,似乎无处不在,在常见的字符串检索或替换中,我们需要提供一种模式表示检索或替换的规则,来匹配一系列符合某个句法规则的字符串。 以下是正则...

  • 35

    正则表达式匹配任意字符(包括换行符) 2019-7-30 20:1:39 | 作者: 月光 | 分类:

  • 17

    前言:网络上SQL注入绕过WAF的帖子文章纷繁多样,良莠不齐,眉毛胡子一把抓,各种姿势让人眼花缭乱。于是,便有学生问我,SQL注入绕过WAF的最本质原理是什么……. 0X01 WAF介绍 要从本质上回答SQL注入...

  • 51
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    柔性多模正则匹配引擎

    分享嘉宾:王彬@奇安信 出品...

  • 11
    • gsl201600.github.io 4 years ago
    • Cache

    iOS 正则匹配常用方法

    2020-07-08 • 于 代码库 阅读 20 iOS 正则匹配常用方法 验证手机号 123

  • 18

    正则表达式量词匹配方式的讲解(上篇)如果想要系统的学习正则表达式的话,那么关于量词的匹配方式是必须要掌握好的内容。量词的匹配方式有三种,分别是「匹配优先」,「忽略优先」以及「占有优先」。今天这篇文章先来讲解一下匹...

  • 6

    PHP中正则表达式对UNICODE字符码的匹配 – CFC4N的博客酷暑难耐,又在家宅一整天。天气热或许是借口,尽管不热,我也喜欢宅在家。晚上看新三国83集(插一句,最近世界杯很火,可是我不看世界杯。来鄙视我吧),一直看到10点半,突然觉得肚子痛,赶紧直奔厕所。如...

  • 21
    • zhuanlan.zhihu.com 4 years ago
    • Cache

    正则表达式匹配素数的原理讲解

    正则表达式匹配素数的原理讲解为什么要写这么一篇文章呢?是因为自己最近在研究和学习正则表达式,然后在RegexGolf上练习技能的时候遇到了这么一道题目,觉得很有趣。我当时虽然也解决了这个问题,但是正则表达式写的有点长,而且也只算是一种...

  • 11

    用正则表达式匹配3的任意倍数 2019-10-21 分类:算法 /

  • 4

    python 正则匹配任意字符的一个坑 – 哈呜.王 错误: .* 是匹配除了换行符\n以外的所有字符。 正确: 正确匹配任意字符的表达式应该是 [\s\S]*...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK