ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-02-02 11:00:00  阅读:223  来源: 互联网

标签:字符 量词 第三章 ... 正则表达式 概览 分组 Unicode 匹配


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

  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提供(这本书比较老了,现在的情况不知道怎样),占有优先量词类似普通的匹配优先量词,不过他们一旦匹配内容,就不会“交还”。他们类似固化分组。

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

标签:字符,量词,第三章,...,正则表达式,概览,分组,Unicode,匹配
来源: https://blog.csdn.net/qq_28849581/article/details/113495235

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有