写点什么

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:081854
用户头像

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

关注

评论

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

新人工作的时候遇到问题怎么办

波波

学习 编程 职场 新人

习惯与惯性

伯薇

个人成长 习惯 习惯养成 提升能力

读懂才会用 : Redis的多线程

小眼睛聊技术

Java redis 学习 程序员 编程语言 后端

技术人赚钱的9个路线

品牌运营|陆晓明

副业 赚钱 技术人 码农 生财有术

瞎琢磨先生の常用的 linux 命令

瞎琢磨先生

Linux Shell

重新认识Go语言中的slice

麻瓜镇

Go 语言

金融「中台」十宗罪

FinClip

中台 企业中台 业务中台

详解iOS性能优化,安装包瘦身

Usama Bin Laden

ios 源码分析 性能优化 性能 原理

开通InfoQ写作平台测试

ytl

Redis源码之常用数据结构和函数

心平气和

redis

系统的伸缩性以及扩展性设计

Janenesome

读书笔记 程序员 架构

赚钱的6个层次

品牌运营|陆晓明

创业 技术人 赚钱思维 层次 商机

关于CodeReview的一些思考

Yezhiwei

Redis学习笔记(基础命令)

编程随想曲

redis

准备重读测试驱动开发

escray

学习 CSD 认证实战营

JAVA小抄-000-初始

NoNoGirl

Java

关于沟通成本的一些认知

Geek_reg5m9

项目管理 软件开发

关于「后浪」,ta 们在说什么?

boyzcl

年轻人 系列 后浪

年轻人的世界

boyzcl

年轻人 系列

信仰

小天同学

人生 个人成长 思考 读书感悟 信仰

在今天种下一棵树

陈医僧Ethan

感悟 育儿

Hello World !

ATGU:阿宝哥

Java Hello World ! Info

[读书随笔]从哲学上的问题分类看TDD

老狗

哲学 TDD

瞎琢磨先生の好物推荐(软件/网站)

瞎琢磨先生

如何利用数据异构实现多级缓存或者数据迁移

松花皮蛋me

缓存 分布式 分库分表

UITableView 手势延迟导致subview无法完成两次绘制

AlienJunX

如何对Code Review的评论进行分级

宝玉

代码审查 Code Review

婚姻就是合伙开公司,各自做好自己的工作很重要

鼎玉谷

管理 婚姻 公司 付出 人情

我也曾对架构师的力量一无所知

曲水流觞TechRill

对你来说,阅读是另一种生活的方式吗?

叶小鍵

基于vue(element ui) + ssm + shiro 的权限框架

吴邪

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