HTML5技术

刨根究底正则表达式之零——前言 - 笨笨阿林(2)

字号+ 作者:H5之家 来源:H5之家 2017-06-02 14:00 我要评论( )

这里需要特别强调一下的是,我绝没有贬低上述这两本专业著作及其作者和/或译者之意,而且恰恰相反,这两本专著正是本系列文章的重要参考书。尤其无论是作为《精通正则表达式》的译者,还是作为《正则指引》的著者,

这里需要特别强调一下的是,我绝没有贬低上述这两本专业著作及其作者和/或译者之意,而且恰恰相反,这两本专著正是本系列文章的重要参考书。尤其无论是作为《精通正则表达式》的译者,还是作为《正则指引》的著者,余晟先生都绝对称得上是既专业又严谨。

4.

那么,前面所谓“更高的维度或层面”,到底指的是什么呢?那就是,从编程语言发展史以及编程范式的角度来看正则表达式。什么?正则表达式竟然也算得上是一门正式的编程语言吗?别急,请继续往下看。

正则表达式有一个非常明显的特点:高度简洁、高度抽象。正则表达式中短短的几个字符,或许就代表了一段复杂的处理逻辑和匹配算法。

5.

我们知道,程序代码是对现实事务处理逻辑的抽象,而正则表达式则是对复杂的字符匹配程序代码的进一步抽象;也就是说,高度简洁的正则表达式,可以认为其背后所对应的是字符匹配程序代码,而字符匹配程序代码,背后对应的是字符匹配处理逻辑。

因此可以这么认为,字符匹配处理逻辑,抽象为字符匹配程序代码;字符匹配程序代码,再进一步抽象为高度简洁的正则表达式。所以说,高度简洁的正则表达式也是高度抽象的。

6.

事实上,从编程语言发展的角度来看,正则表达式也是一种编程语言,而且是属于第4代语言(4GL)——面向问题语言(第1代语言为机器语言——由0和1组成的位串,第2代语言为汇编语言——用接近于英语单词的助记码mnemonic code来代替由0和1组成的位串,第3代语言为高级语言——用接近于自然语言的语法元素编写程序,如C/C++、Java、C#、Perl、Python、PHP、JavaScript等语言,第4代语言为面向问题语言——用针对问题领域专门设计的语法元素编写程序或表达式,如SQL、SAS、SPSS、LaTeX、Regex(即正则表达式)等,第5代语言为人工智能语言——Prolog、Mercury、OPS5等;不过,从第4代语言到第5代语言的演化还不是很清晰,目前学术界争议较大,这里不作讨论)。

【注:这里强烈推荐郑晖先生所著的《冒号课堂——编程范式与OOP思想》一书,该书既以宏观视角,纵向审视了编程语言发展简史,横向比较了各类编程语言的特点;又以微观实践,娓娓道来各编程范式的优劣得失,更是深入探讨了面向对象编程的方方面面,是不可多得的一本中文原创计算机专著。这里是我在豆瓣写的该书书评,供参考。】

 

第4代语言相对于第3代语言,更专注于其所应用或者说其所适用的某个特定的业务逻辑和问题领域。程序员主要负责分析问题,以及使用第4代语言来描述问题,而无需花大量时间去考虑具体的处理逻辑和算法实现(事实上,最初之所以提出第4代语言的概念,就是希望非专业程序员也能做应用开发,虽然后来的发展事实证明并没有很好地实现这一目的)。

7.

从编程范式(Programming Paradigm)的角度上来讲,第4代语言属于声明式编程范式,声明式编程重在目标而非过程、重在描述而非实现,以声明式语句直接描述问题,专注于问题的分析和表达,而非专注于处理逻辑和算法实现过程,其具体的处理逻辑和算法实现是由语言解析引擎(编译器或解释器)来负责的。

当然,这样一来,这些由语言解析引擎实现的处理逻辑和具体算法其通用性就会较差,只能适用于某些特定业务或特定领域。也正是这个原因,第4代语言基本都是局限于某些特定领域的,多被认为是领域特定语言DSL(Domain Specific Language)。

区别于算法实现可由程序员自由灵活设计的通用编程语言GPPL(General-Purpose Programming Language,作为第3代语言的高级语言基本上都属于通用编程语言),领域特定语言DSL的算法基本上由语言解析引擎自动实现,程序员灵活设计、自由发挥的空间很小,因此DSL几乎没有通用性(而且DSL大都是非图灵完备的语言),只能专用于解决特定业务方向和业务领域的问题。

比如,SQL是专用于数据库操作的语言、SAS和SPSS是专用于统计分析的语言、LaTeX是专用于排版的语言,而正则表达式Regex(Regular expression)则是专用于处理字符匹配的语言。

8.

理解了这一点,就比较容易理解正则表达式是字符匹配处理逻辑的抽象;更进一步地来说,正则表达式中的某些元字符与特殊结构,可理解为某种具体的程序逻辑和算法的体现。

比如,正则表达式中的量词*这一元字符,就是高级语言的处理逻辑“循环结构”的体现(具体来说量词*代表的是不定次数循环),而前后多个量词的嵌套就是多层循环的嵌套;或运算符|这一元字符,就是高级语言的处理逻辑“选择结构”的体现。

而当或运算符|出现在由量词*所限定的圆括号中时,其实就是“循环结构”中嵌套了“选择结构”;而如果进一步地,“循环结构”所嵌套的“选择结构”中的某个分支,又被某个量词*所限定,那么则相当于“循环结构”所嵌套的“选择结构”又嵌套了“循环结构”。

理解这一点非常重要,是快速、深入理解正则表达式的一把钥匙、一条捷径。站在编程语言发展史和编程范式的高度,再结合对正则表达式本身原理的深入理解,里外结合,高下相较,既登高望远、一览众山小,又洞幽烛微、复观千水深,正则表达式的奥义,就能尽在掌握之中了。

9.

当然,正则表达式之所以难学、难理解,除了由于正则表达式作为一个字符匹配领域的领域特定语言(DSL),具有高度简洁、高度抽象的特点之外,大致上应该还有以下几个原因:

1)  学习者不求甚解,不了解正则引擎内部的基本原理

作为正则表达式的使用者,不需要深入了解正则引擎内部原理的技术实现细节,那是正则引擎开发者更应该了解的;但若完全不了解其基本工作原理和运行机制,也是不足取的。

2)  有多个多义元字符,特别容易使人混淆、迷乱

比如-、+、?、^,尤其是元字符?,既可以作为量词表示其所限定的子表达式为可选(即匹配0次或1次),也可以置于量词之后表示懒惰匹配,而且还有很多特殊分组结构中用到它,比如(?<name>sub-regex)、(?:sub-regex)、(?>sub-regex)、(?=sub-regex)、(?!sub-regex)、(?<=sub-regex)、(?<!sub-regex)、(?|sub-regex)、(?modifier-modifier)、(?(condition)|)、(?R)、(?num)、(?#comment)等;还记得我自己当初刚开始学习的时候,一看到正则表达式中的问号?,就有一种独自在风中凌乱的感觉。

3)  转义也是难点

什么情况下需要转义,什么情况下不需要转义,貌似复杂得令人抓狂;当然,其实是有一定的规律的,掌握了这些规律,再遇到转义问题,就不至于心潮澎湃了。

4)  学习期望与学习方法不对

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Java 8 Lambda 表达式 - Felix_ICanFixIt

    Java 8 Lambda 表达式 - Felix_ICanFixIt

    2017-04-22 17:04

  • C# 快速高效率复制对象另一种方式 表达式树 - Emrys5

    C# 快速高效率复制对象另一种方式 表达式树 - Emrys5

    2017-04-06 14:00

  • Omi v1.0.2发布 - 正式支持传递javascript表达式 - 【当耐特】

    Omi v1.0.2发布 - 正式支持传递javascript表达式 - 【当耐特】

    2017-03-22 11:03

  • 【.net 深呼吸】细说CodeDom(2):表达式、语句 - 东邪独孤

    【.net 深呼吸】细说CodeDom(2):表达式、语句 - 东邪独孤

    2016-12-13 12:00

网友点评
'