写点什么

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

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

关注

评论

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

Hologres揭秘:深度解析高效率分布式查询引擎

阿里云大数据AI技术

2021年Java开发实战!仿微信的网络聊天室项目开发【完整源码讲解

策划Java工程师

Java 程序员 后端

Selenium 4以后,再不相见的API

FunTester

自动化 API selenium

2021金三银四,开发者进阿里必看的30道经典数据库面试题【附详细解析

策划Java工程师

Java 程序员 后端

Java入门视频教程!Kotlin(2)-泛型与集合

Java 程序员 后端

防火墙 Keepalived 异常双活恢复后部分外网访问中断问题分析

Qunar技术沙龙

运维 防火墙 网络 故障诊断 keep-alive

2021Java春招面试真题详解,Git-如何优雅地回退代码

策划Java工程师

Java 程序员 后端

5分钟搞定!从Java底层分析多线程行为

Java 程序员 后端

解决方案|在线自习室

anyRTC开发者

音视频 在线教育 RTC RTM

IBM大面积辞退40岁+的员工,瞧一瞧

Java 程序员 后端

从河南暴雨、疫情反弹看区块链“灾疫”治理

CECBC

Python代码阅读(第2篇):数字转化成列表

Felix

Python 编程 Code Programing 阅读代码

2021Java笔试题总结!Java个人学习之旅(第十天)

策划Java工程师

Java 程序员 后端

2021Java面经:Android屏幕适配-重点盘点

策划Java工程师

Java 程序员 后端

2021年五面蚂蚁,从单体到分布式,必须解决的四个问题

策划Java工程师

Java 程序员 后端

graphql计算指令之@filter:查询中实现集合过滤

杜艮魁

开源 后端 低代码 graphql

2021BTAJ面试真题详解,16条代码规范建议,快看看自己做到没

Java 程序员 后端

Java入门你值得拥有!天天都是面对对象编程,你真的了解你的对象吗

Java 程序员 后端

带你使用FFMPEG将MP4视频文件转换为GIF

hanaper

网络攻防学习笔记 Day95

穿过生命散发芬芳

态势感知 网络攻防 8月日更

2021最新Java面试真题解析!1

策划Java工程师

Java 程序员 后端

15个经典面试问题,酸!校招进字节跳动

Java 程序员 后端

3个月学会Java开发!Git-如何优雅地回退代码(1)

Java 程序员 后端

2021年Java知识体系总结,部门老大:redis-分布式锁再这么用

策划Java工程师

Java 程序员 后端

graphql计算指令之@sortBy:查询中实现列表字段排序

杜艮魁

开源 后端 低代码 graphql

80后程序员感慨中年危机,如何设计一个优雅的RESTFUL的接口

Java 程序员 后端

2021Java大厂面试集合,java多线程

策划Java工程师

Java 程序员 后端

【最不佳实践】Serverless应用优化四则

刘宇

Serverless 优化

2021程序员进阶宝典!《零基础(1)

策划Java工程师

Java 程序员 后端

Java入门你值得拥有!浅谈Facade外观模式

Java 程序员 后端

230页,看完之后你就会知道,原来Redis还能这么玩!

Java架构师迁哥

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