写点什么

Jeff Moser 解释.NET 正则表达式的工作方式

  • 2009-04-02
  • 本文字数:1017 字

    阅读完需:约 3 分钟

Jeff Moser 发表了一篇对.NET 中正则表达式工作方式的深入解析。他的文章谈及了微软实现中的一些核心操作原理,如编译正则表达式时使用的机器码。

他首先透露,最近使用的 15 个正则表达式会被缓存起来。对于那些只使用 1 到 2 个正则表达式的小型的应用程序,这意味着没有必要每次都创建一个 Regex 对象。

在编译正则表达式的时候,首先会通过一个扫描器(scanner)来生成(emit)一个 RegexTree。它的叶子节点就好像一种略加扩展的源代码,而下一步便是把它转换为正则表达式引擎所使用的机器码。

这些工作由 EmitFragment 函数完成,其中包含了大约 250 行的 switch 语句。这个函数把 RegexTree 打散成“碎片”再将它们转化为相对简单的 RegexCode

[…]

这些工作生成一个用于描述 RegexCode“操作码”及其参数的整数数组。例如,你可以看到一些例如“ Setrep ”的指令携带了一些字符串参数。这些参数指向了一个字符串表中的偏移量。这就是为什么说,正如我们之前看到的那样,把所有的东西打包成那些不规则字符串是很重要的原因。这是唯一可以传递指令信息的方法。

把代码数组分解之后,我们可以看到:

索引

指令

操作码 / 参数

字符串表的引用

描述

复制代码
[Lazybranch](http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L73)

23

复制代码
延迟扩展至偏移量为 21 的 [Stop](http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L91) 指令。

1

复制代码
21
2

Setmark

31

复制代码
把我们当前的状态放入栈中以便稍后进行回溯。

3

Multi

12

复制代码
对字符串表中的第 0 项(即“http://”)进行一次多字符匹配。

4

复制代码
"http://"

5

Setmark

31

复制代码
把我们当前的状态放入栈中以便稍后进行回溯。

6

Setrep

2

复制代码
对于字符串表中位置为 1 的集合(即\[^\\s/\])进行长度为 1 的反复匹配。

7

复制代码
1

“\x1\x2\x1\x2F\x30\x64”

8

复制代码
1
9

Setloop

5

复制代码
在最多为 Int32.MaxValue 次的循环中对\[^\\s/\] 集合进行匹配。

10

复制代码
1

“\x1\x2\x1\x2F\x30\x64”

11

复制代码
2147483647
12

Capturemark

32

复制代码
捕获组#1,即最近一次 Setmark 所标记的位置,到当前位置的字符串。

13

复制代码
1
14
-1
15

Oneloop

3

复制代码
在最多为 1 次的循环中匹配 Unicode 字符 47

16

复制代码
47
17
1
18

Capturemark

32

复制代码
捕获组#0,即第一次 Setmark 所标记的位置,到当前位置的字符串。

19

复制代码
20
-1
21

Stop

40

复制代码
停止匹配。

可以看到,正则表达式已经被转化为一个稍后可供运行的简单“程序”。

Jeff Moser 的博客中描述了有关这个过程的更多信息。他的文章还讨论了:

  • 前缀优化
  • 解释器
  • 回溯
  • 已知错误

查看英文原文: Jeff Moser’s How .NET Regular Expressions Really Work

2009-04-02 21:081532
用户头像

发布了 157 篇内容, 共 56.3 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

【21-1】21 连更第一篇

耳东@Erdong

6月日更

SpringBootApplication注解

梦倚栏杆

☕️【Java技术之旅】站在Linux操作系统角度去看Thread(线程)

洛神灬殇

线程 Thread 6月日更 内核线程

缓存穿透、缓存雪崩、缓存击穿问题与优化方案

Skysper

Python——字符串转换与处理

在即

6月日更

读深入ES6记[二]

蛋先生DX

ES6 6月日更

【LeetCode】从上到下打印二叉树 Java题解

Albert

算法 LeetCode 6月日更

待办事项列表,敏捷项目管理的核心工件

万事ONES

Scrum 敏捷 研发管理 ONES

高性能 JavaScriptの七 -- 编程实践小技巧

空城机

JavaScript 大前端 6月日更

【布道API】浅谈API设计风格

devpoint

Rest API 6月日更

这些书都学完,绝对是编程界的大佬

看山

Java 程序员 6月日更

Kubernetes 的自动伸缩你用对了吗?

张晓辉

Kubernetes k8s最佳实践

内嵌双向链表的设计与实现

实力程序员

一文教会你认识Vuex状态机

华为云开发者联盟

Vue 应用 vuex 事件 父子组件

【Vue2.x 源码学习】第八篇 - 数组的深层劫持

Brave

源码 vue2 6月日更

递归全排列问题(两种方法 Java实现)

若尘

数据结构 递归 6月日更

【Flutter 专题】109 图解自定义 ACERadio 单选框

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 6月日更

如何进行可视化大屏视觉设计?

博文视点Broadview

Java 并发编程——线程池开篇

Antway

6月日更

那个陪我打王者的兄弟进了阿里

艾小仙

Locust完成gRPC协议的性能测试

陈磊@Criss

Webpack 系列:如何编写loader

范文杰

webpack 6月日更

春色满园关不住,带你体验阿里云 Knative

阿里巴巴云原生

云原生

密码学系列之:生日攻击

程序那些事

加密解密 密码学 程序那些事

聊聊追求测试技术导致过度测试

陈磊@Criss

你愿意被管理么?

escray

学习 极客时间 朱赟的技术管理课 6月日更

Mybatis 二级缓存简单示例

Java mybatis

当人工智能遇上视频直播——基于Agora Web SDK实现目标识别

dajyaretakuya

深度学习 音视频 WebRTC 声网 TensorFlow.js

Packer 自动化镜像 Windows 安装过程

HoneyMoose

模块六作业

c

架构实战营

证券互动问答平台关键词监控提醒

木头

互动平台 证券监控 股市消息 监控提醒

Jeff Moser解释.NET正则表达式的工作方式_.NET_Jonathan Allen_InfoQ精选文章