精通正则表达式第三章:正则表达式的特性和流派概览

程序设计语言处理正则表达式的方式

  1. 集成式:表达式直接内建在语言之中,如Perl
  2. 程序式和面向对象式:正则表达式不属于语言的低级语法。相反,普通的函数接受普通的字符串,把他们作为正则表达式进行处理。

集成式处理

集成式处理方法减轻了程序员的负担,因为它隐藏了一些工作,例如正则表达式的预处理,准备匹配,应用正则表达式,返回结果。但是有时这样处理反而更慢,更复杂。

程序式处理和面向对象式处理

正则功能不是由内建的操作符来提供,而是由普通函数(函数式)或构造函数(面向对象式)来提供的。
Java中的正则处理

常用元字符和特性

字符组及相关结构

  1. 普通字符组:[a-z][^a-z],需要强调的是,元字符的规定在字符组内外饰有差别的。例如,字符组内部的*永远都不是元字符,二-通常都是元字符。有些元序列\b在字符组内外是不一样的。
    字符组通常表示肯定断言。也就是说他们必须匹配一个字符。排除型字符组仍然需要匹配一个字符,只是她没有在字符组内列出而已。

几乎能匹配任何字符的元字符:点号

在某些工具软件中,点好被用来缩略表示可以匹配任何字符的字符组,而在其它工具中,点号匹配除了换行符之外的任何字符。

  1. 在Sun的Java regex package 之类的支持Unicode的系统中,点号不能匹配Unicode的行终结符。
  2. 匹配模式会改变点号的匹配规则。
  3. POSIX规定,点号不能匹配NUL(值为0的字符),尽管大多数脚本语言容许文本中出现NUL(而且可以用点号来匹配)。

点号还是排除型字符组

如果所使用的工具能够在多行文本中进行搜索,请务必注意点号,它通常情况下不能匹配换行符,而排除型字符组[^"]通常都可以。如果把".*"替换为"[^"]",可能会带来意想不到的效果。

单个字节

Perl和PCRE(也包括PHP)支持用\C匹配单个字节,即使该字节位于某个多字节编码的字符之中(相反,其他功能都是基于字符的)。这个功能一定要在清楚自己的所作所为下才使用。

Unicode组合字符序列:\X

Perl和PHP支持使用\X缩略表示\P{M}\p{M}*,它可以视为点号的扩展,它匹配一个基本字符(除了\p{M}之外的任何字符),之后可能有任意数量的组合字符(出\p{M}之外)。

字符组简记法:\w , \d, \s, \W, \D, \S

\d:数字,等价于[0-9],如果工具软件支持Unicode,能匹配所有的Unicode数字。
\D:非数字字符 等价于[^\d]
\w: 单词中的字符,=一般等价于[a-zA-Z0-9_],某些工具软件中\w不能匹配下划线,而另一些工具软件中的\w能支持当前locale中的所有数字和字符。如果支持Unicode,\w通常能匹配所有数字和字符,而在java.util.regex和PCRE(包括PHP)中,\w严格等价于[a-zA-Z0-9_]
\W:非单词字符 等价于[^\w]
\s:空白字符,在支持ASCII的系统中,它通常等价于\f\n\r\t\v(第一个是空白字符)。有时包括Unicode的”换行“字符U+0085,有时包含空白(whitespace)属性\p{M}
\S:非空白字符, 等价于[^\s]
POSIX的locale设定会影响这些简记符号的含义(尤其是\w)。支持Unicode的程序中,\w通常能匹配更多的字符,例如\p{L}和下划线。

Unicode属性,字母表和区块:\p{Prop}\P{Prop}

Unicode不仅仅是一套字符规则,他还定义了每个字符的性质,例如”这个字符是小写字母“,”这个字符是从右往左看的“,”这个字符是标记字符,他必须与其他字符一同使用“等等。

不同的正则表达式系统对这些属性的支持也不相同,但是许多支持Unicode的程序能够通过\p{quality}\P{quality}支持其中的一部分。比如\p{L}就是一个简单例子,这里'L'的意思是”字母(letter)“(相对于数字number,标点qunctutation和口音accent,之类)。'L'是一种普通属性(general property,也成为分类)。我们马上会了解到,可以用\p{...}\P{...}来测试其他属性。
字母表:有的系统能够按照字母表(书写系统writing system)的名字以\p{...}来匹配。例如\p{Hebrew}匹配希伯来文独有的字符(但不包含其他书写系统中常见的字符,例如空格和标点)。
字母表不会包含特定书写系统中的所有字符,而只包含独属于(或者几乎独属于)此书写系统中的字符。常见的字符,如空格和标点不属于任何字母表,而是属于通用的IsCommon伪字母表(pseudo-script),用\p{IsCommon}匹配。
区块:类似于字母表,区块表示Unicode字符映射中一定范围内的代码点。

简单的字符组减法

[[a-z]-[aeiou]]就是匹配小写非元音字母

完整的字符组集合运算:[[a-z] && [^aeiou]]

OR运算:用于将多个字符组合并
AND对两个集合进行概念上的“与”运算,只保留同时属于两个字符组的字符。

POSIX“字符组”方括号表示法

我们通常所说的字符组,在POSIX标准中成为方括号表达式(bracket expression)。POSIX字符组是POSIX方括号表达式使用的几种特殊元字符序列之一。比如[:lower:]表示当前locale中的所有小写字母。它还包含一些特殊的小写字母(在locale)中定义的。

POSIX“collating序列”方括号表示法:[[ span-ll ]]

Local可以包含对应的collating序列,用来决定其中的字符如何排序。

POSIX“字符等价类”方括号表示法:[[=n=]]

有的locale定义了字符等价类,表示某些字符在进行排序之类的操作时应视为等价。

锚点和其他零长度断言

这两个东西并不会匹配实际的文本,而是寻找文本中的位置。

行/字符串起始位置:^\A

如果可以使用,\A总是匹配待搜索文本的起始位置。

行/字符串的结束位置:$\z\Z

如果支持,\Z通常表示“未指定任何模式下”$匹配的字符,通常是字符串末尾的位置,或者是在字符串末尾的换行符之前的位置。作为补充,\z只匹配字符串的末尾,而不考虑任何换行符。

匹配的起始位置(或者是上一次匹配结束的位置):\G

\G首次出现在Perl中。使用/g的匹配中,\G对迭代操作非常有用,它能够匹配上一次匹配结束的位置。在第一次迭代中,\G匹配字符串的开头,与\A一样。

分组,捕获,条件判断和控制

捕获/分组括号:(…)和 \1, \2, …

普通的无特殊意义的括号通常由两种功能:分组和捕获。普通括号常见的形式是(...),但有的流派中使用\(...\),例如FNU Emacs,sed,vi和grep。

仅用于分组的括号

仅用于分组的括号(?:...)不能用来提取文本,而只能用来规定多选结构或者两次的作用对象。因此也被称为“非捕获型括号”。

命名捕获(?<Name>...)

Python和PHP的preg引擎,都能够为捕获内容命名。python和PHP使用的语法是(?P<name>...),而.NET使用(?<name>...)

\b(?<Area>\d\d\d)-(?<Exch>\d\d\d)-(?<Num>\d\d\d)\b

可以用对应的方法提取命名捕获的内容,如在VB和.NET语言中使用RegexObj.Groups(“Area”),在PHP中使用RegexObj.group(“Area”)。

固化分组:(?>...)

一旦括号内的子表达式匹配之后,匹配的内容就固定下来(固化(atomic)下来无法改变),在接下来的匹配过程中不会变化,除非整个固化分组的括号都被弃用,在外部回溯中重新应用。
表达式。.*!能够匹配文本。Hola!,但是表达式。(?>.*)!却不能。因为使用了固化分组,在.*在固化分组中,他永远不会“交还”已经匹配的任何内容。

固化分组有重要的用途。尤其是,能够提高匹配的效率,而且能够对什么匹配,什么不能匹配进行精确地控制。

多选结构

多选结构能够在同一位置测试多个子表达式。每个子表达式称为一个多选分支(alternative)。多选结构的优先级很低,所以this and|or that的匹配等价于(this and)|(or that),而不是this (and|or) that

条件判断:(?if then | else)

可以根据已经匹配的结果选择下一步要用哪个子表达式进行匹配。下面的例子匹配<IMG> tag,无论是单独出现的,或者是在<A>...</A>中出现的。

(<A\s+[^>]+> \s* )?  #匹配开头的<A> tag,如果存在的话
<IMG\s+[^>]+>		#匹配<IMG> tag
(?(1)\s*</A>)       #匹配结尾的</A>,如果之前匹配过<A>

(?(1)...)测试中的(1)会测试第一组捕获型括号是否参与了匹配。“参与匹配”不等于实际匹配了文本。

匹配优先量词:*, +, ?, {num,num}

要注意在某些工具中可能使用\+\?来取代+?。同样,在更老的某些工具中,量词不能限定反向引用,也不能限定括号。

区间:{min,max}或者{min,max \}

区间可以被认为是“计数量词”

忽略优先量词:*?, +?, ??, {num,num}?

量词在正常的情况下都是匹配优先的,匹配尽可能多的内容。相反,这些忽略优先的量词会匹配尽可能少的内容,只需要满足下限,匹配就能成功。

占有优先量词:*+, ++, ?+, {num,num}+

这些量词目前只有java和PCRE提供(这本书比较老了,现在的情况不知道怎样),占有优先量词类似普通的匹配优先量词,不过他们一旦匹配内容,就不会“交还”。他们类似固化分组。

从某种意义上来说,占有优先量词只是些表面功夫,因为它们可以用固化分组模拟实现。
.++?>.+的结果完全一样,只是足够智能的实现凡是能对占有优先量词进行更多优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
随着互联网的迅速发展,几乎所有工具软件和程序语言都支持的正则表达式也变得越来越强大和易于使用。《精通正则表达式(第3版)》是讲解正则表达式的经典之作。《精通正则表达式(第3版)》主要讲解了正则表达式特性流派、匹配原理、优化原则、实用诀窍以及调校措施,并详细介绍了在Perl、Java、.NET、PHP中正则表达式的用法。 《精通正则表达式(第3版)》自第1版开始着力于教会读者 "以正则表达式来思考",来让读者真正"精通"正则表达式。该版对PHP的相关内容、Java1.5和Java1.6的新特性作了可观的扩充讲解。任何有机会使用正则表达式的读者都将因《精通正则表达式(第3版)》而受益匪浅。 《精通正则表达式(第3版)》讲解正则表达式,这种工具能够提高工作效率、让生活变得更轻松。精心调校后的正则表达式只需要十多秒就能完成以前数小时才能完成的枯燥任务。如今,正则表达式已经成为众多语言及工具--Perl、PHP、Java、Python、Ruby、MysQL、VB-NET和c#(以及.NETFramework中的任何语言)--中的标准特性,依靠它,你能以之前完全不敢设想的方式进行复杂而精巧的文本处理。十年三版,再显王者风范,近30年开发经验的智慧结晶,深入理解正则表达式,彻底修炼基本功,全球第一本全面深入讲解正则表达式的经典巨著,《程序员》杂志技术主编孟岩鼎力推荐。 专家点评:《精通正则表达式》是系统学习正则表达式的唯一最权威著作。任何时候,任何地方,只要提到正则表达式著作,人们都会提到这本书。该书质量之高,声誉之盛,使得几乎没有人企图挑战它的地位,从而在正则表达式图书领域形成了独特的"一夫当关"的局面,称其为正则表达式圣经,绝对当之无愧。 --《程序员》杂志技术主编孟岩 《精通正则表达式(第3版)》包含了对PHP及其正则表达式的讲解。这一版的更新也反映了其他语言的发展,深入讲解了Sun的java.util.regex,并特别提到了Java1.4.2和Java1.5/1.6之间的众多差异。 本书的内容: ·各种语言和工具的功能比较 ·正则引擎的工作原理 ·优化(能节省大量的时间) ·准确匹配期望的文本 ·针对具体语言的章节 《精通正则表达式(第3版)》,以明晰轻松的笔调向程序员深入浅出地讲解复杂的知识,并给出了现实世界中复杂问题的解决办法,读者能够立刻运用书中丰富的知识,巧妙而高效地解决各种问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值