(转)为什么需要正则表达式 by 王珢
为什么需要正则表达式
by 王垠
学习Unix最开头,大家都学过正则表达式(regexp)。可是有没有人考虑过我们为什么需要正则表达式?
正则表达式本来的初衷是用来从无结构的字符串中提取信息,殊不知这正好是Unix的缺陷所在。Unix用无结构的字符串来表示数据,导致了诸多复杂的基于regexp的软件的诞生。sed, AWK, Perl, … 都是为了同样的目的来到这个世界上的。如果不是因为Unix用字符串来表示数据,我们就会拥有按数据结构类型的直接存储,而不需要折腾regexp。正则表达式有它自己的价值(针对自然语言),但是我们其实不需要把它应用到程序语言和操作系统里面。
正则表达式本身用一个字符串来表示,这带来另外一些问题。因为正则表达式的本质不是字符串,而是一个数据结构。学过计算理论的人可能知道这个数据结构叫做NFA(nondeterministic finite automaton,非确定性有限自动机)。所有的数据结构应该由程序语言本身来表示,就像用Java构造一个对象用 new ClassA("a") 一样。但是正则表达式强迫你把这个简单的构造函数调用写成一个字符串。所以在这个比方之下,你得写成new ClassA(\"a\")。这样当你想要组合这些表达式的时候就发现,正则表达式几乎都是不可组合(compose)的。你几乎不可能不能把两个regexp的变量A和B安全拼接成一个,比如用Java的字符串拼接A+B。因为你不知道这两个字符串拼在一起之后,那些稀奇古怪的符号会出现什么交叉反应,使得最后的识别的东西根本不是你想要的。
在正则表达式中,由于正则表达式本身的构造函数与数据本身合并到一起,我们不得不对某些“特殊字符”进行escape。这些特殊字符,其实是用来描述NFA的记号,它们属于更高一层的语言。可是在正则表达式里,它们与NFA节点里的字符混为一谈。比如很简单的一个block comment的正则表达式,却要写成这个样子:
/\\*([^\\*]|[^/])*\\*/
显然这样的表达式很容易出错。 如果我们用程序语言的表达式来构造这个表达式,它应该是这样:
(@... "/*" (@*(@!"*/")) "*/" )
在这个我自己设计的Scheme表达式里,以@开头的标识符都是构造函数。其中@...是构造sequence,@* 是构造一个zero-or-more的匹配,@!构造一个否定匹配。这个表达式是说:“以/ *开头,接着零个或者多个不是* /的字符,最后接着一个* /。这样一来清晰明了,什么表达式在什么“层次”都很清楚,不需要什么反斜杠escape,而且这样的表达式可以compose。比如:
(define reg1 (@... "/*" (@*(@!"*/")) "*/" ))
(define reg2 (@+ "foo"))
(define reg3 (@= "b"))
定义这三个表达式之后,我们之后可以用像(@... reg1 (@or reg2 reg3)) 这样的表达式来连接3个不同的表达式,构造出更大的表达式。这样的构造可以无限的扩展。从这里以及以往的经验,我总结出一个普遍适用的程序设计的教训:尽量不要把多个层次的语言“压缩”到一层。我们也看到正则表达式与“Unix哲学”有很大关系。我没有考古,所以不知道孰先孰后,但是它们肯定有直接的因果关系。两者都是Unix复杂性的来源。
This article was posted at yinwang’s sina blog,
on 2012-05-17.
Though it’s not available now.
(转)为什么需要正则表达式 by 王珢的更多相关文章
- (转)完全用GNU/Linux工作 by 王珢
完全用GNU/Linux工作 王珢 (看完这篇博文,非常喜欢王珢的这篇博客,也我坚定了学gnu/linux的决心,并努力去按照国外的计算机思维模式去学习编程提高自己.看完这篇文章令我热血沸腾 ...
- (转)什么是“黑客” by 王珢
什么是“黑客” by 王垠很多程序员自豪的把自己叫做“黑客”(hacker),把编程叫做 hack.可是殊不知,其实在最高级的程序员眼里,“黑客”其实是一个贬义词.他们更愿意被叫做“程序员”(prog ...
- (转)对博士学位说永别 by 王珢
对博士学位说永别 by 王垠 经过深思熟虑之后,我决定再次“抛弃”我的博士学位.这是我第三次决定离开博士学位,也应该是最后一次了.这应该不是什么惊人的消息,因为我虽然读博士10年了,可是我的目标从来就 ...
- (转)名称和本质 by王珢
名称和本质 by 王垠 我很喜欢 Richard Feynman 写的 <What Do You Care What Other People Think>.在最开头 Feynman 讲到 ...
- (转)小小科学家的归来 by 王珢
小小科学家的归来 by 王垠很多人来信关心我的现状,所以在写别的技术性文章之前,先说说我现在的情况吧.虽然自己追求的东西和经历都比较不同寻常,但是也许可以给奋斗中的人们一些慰藉和鼓励. 首先是超级好消 ...
- (转)我看PhD by 王珢
我看PhD by 王垠 前段时间看了一下这些关于 PhD 的负面信息: 一个专门反对读 PhD 的 BLOG 叫“100 Reasons NOT to Go to Graduate School”(下 ...
- Python 正则表达式入门(初级篇)
Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...
- python基础之正则表达式
正则表达式语法 正则表达式 (或 RE) 指定一组字符串匹配它;在此模块中的功能让您检查一下,如果一个特定的字符串匹配给定的正则表达式 (或给定的正则表达式匹配特定的字符串,可归结为同一件事). 正则 ...
- SQL中常用模糊查询的四种匹配模式&&正则表达式
执行数据库查询时,有完整查询和模糊查询之分.一般模糊语句如下:SELECT 字段 FROM 表 WHERE 某字段 Like 条件 其中关于条件,SQL提供了四种匹配模式:1.%:表示任意0个或多个字 ...
随机推荐
- MQTT(三)-----连接与心跳
MQTT协议笔记之连接和心跳 - 推酷 http://www.tuicool.com/articles/AFvmee 互联网推送服务原理:长连接+心跳机制(MQTT协议) - clh604的专栏 - ...
- struts2download
public class TestAction extends ActionSupport{ public String fileLoad() throws IOException{ ...
- ABAP READ TABLE语句注意
READ TABLE 后注意判断 sy-subrc 是否等于0
- 第18讲——ActiveX控件
1,容器应用程序是可以嵌入或链接对象的应用程序.服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序. 2,可以安装一个TstCon32来测试ActiveX控件 3,可以用 Invalid ...
- js中子页面父页面方法 变量相互调用
(1)子页面调用父页面的方法或者变量: window.parent.方法()或者变量名window.parent相当于定位到父页面 之后的操作和在父页面中写代码一样写 window.parent.a ...
- [Android Pro] 精确记录和恢复ListView滑动位置
reference to : http://blog.csdn.net/welovesunflower/article/details/7926512 工作中遇到一个需求,对ListView某一项操作 ...
- MFC 创建多层目录
创建多层目录 BOOL CTestToolCtr::CreateFolder(CString strNewFolder) { /************************************ ...
- KNN识别图像上的数字及python实现
领导让我每天手工录入BI系统中的数据并判断数据是否存在异常,若有异常点,则检测是系统问题还是业务问题.为了解放双手,我决定写个程序完成每天录入管理驾驶舱数据的任务.首先用按键精灵录了一套脚本把系统中的 ...
- .net学习笔记---tcp/udp/http/socket
什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议.这种协议可以提供面向连接的.可靠的.点到点的通信. UDP全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信. 使用 ...
- SVN使用教程之-分支/标记 合并 subeclipse (转)
首先说下为什么我们需要用到分支-合 并.比如项目demo下有两个小组,svn下有一个trunk版.由于客户需求突然变化,导致项目需要做较大改动,此时项目组决定由小组1继续完成原来正 进行到一半的工作[ ...