《精通正则表达式》学习笔记,第一章 正则表达式入门

 

  • 脱字符号「 ^」和美元符号「 $」

在检查一行文本时,「 ^」代表一行的开始,「 $」代表结束。「 ^」用来把匹配文本(这个表达式的其他部分匹配的字符) “锚定”( anchor)在这一行的开头。同样,「 cat$」只寻找位于行末的c–a–t,如以scat结尾的行。
字符号和美元符号的特别之处就在于,它们匹配的是一个位置,而不是具体的文本。

  • 字符组(character class):「 […] 」

正则表达式结构体( construct)「 […] 」。 它容许使用者列出在某处期望匹配的字符, 通常被称作字符组。「 e」匹配字符e,「 a」匹配字符 a, 而正则表达式「 [ea]」能匹配a或者e。 所以,「 gr[ea]y」的意思是: 先找到g, 跟着是一个r, 然后是一个a或者 e, 最后是一个y。
字符组内部, 字符组元字符( character-class metacharacter) ‘-’( 连字符) 表示一个范围:「 <H[1-6]>」与「 <H[123456]>」是完全一样的。有在字符组内部,连字符才是元字符——否则它就只能匹配普通的连字符号。其实, 即使在字符组内部, 它也不一定就是元字符。 如果连字符出现在字符组的开头, 它表示的就只是一个普通字符, 而不是一个范围。 同样的道理, 号和点号通常被当作元字符处理, 但在字符组中则不是如此( 说明白一点就是,「 [0-9A-Z_!.?]」里面, 真正的特殊字符就只有那两个连字符)。

  • 排除型字符组:「 [^…]」

用「 [^…]」取代「 […]」, 这个字符组就会匹配任何未列出的字符。 例如,「 [^1-6]」匹配除了1到6以外的任何字符。这个字符组中开头的「 ^」表示“排除( negate) ”,所以这里列出的不是希望匹配的字符,而是不希望匹配的字符。
请记住,排除型字符组表示“匹配一个未列出的字符 ( matchacharacterthat'snotlisted)”,而不是“不要匹配列出的字符( don'tmatchwhatislisted) ”

注:这里的^和表示行首的脱字符是一样的。字符确实相同,但意义截然不同。英语里的“wind”,根据情境的不同,可能表示一阵强烈的气流(风),也可能表示给钟表上发条; 元字符也是如此。 我们已经看过用来表示范围的连字符的例子。 只有在字符组内部(而且不是第一个字符的情况下),连字符才能表示范围。在字符组外部, ^表示一个行锚点( line anchor), 但是在字符组内部( 而且必须是紧接在字符组的第一个方括号之后),它就是一个元字符。

  • 点号匹配任意字符:「 .」

元字符「 .」(通常称为点号dot或者小点point)是用来匹配任意字符的字符组的简便写法。 如果我们需要在表达式中使用一个“匹配任何字符”的占位符( placeholder), 用点号就很方便。 例如, 如果我们需要搜索03/19/76、 03-19-76或者03.19.76, 不怕麻烦的话用一个明确容许‘/’、 ‘-’、 ‘.’的字符组来构建正则表达式,例如「 03[-./]19[-./]76」。也可以简单地尝试「 03.19.76」。

  • 多选结构(Alternation),匹配任意子表达式:「 |」

「 |」是一个非常简捷的元字符,它的意思是“或”( or)。 我们能够把不同的子表达式组合成一个总的表达式,而这个总的表达式又能够匹配任意的子表达式。假如「 Bob」和「 Robert」是两个表达式,但「 Bob|Robert」就是能够同时匹配其中任意一个的正则表达式。在这样的组合中,子表达式称为“多选分支( alternative) ”。
回头来看「 gr[ea]y」的例子,有意思的是,它还可以写作「 grey|gray」,或者是「 gr(a|e)y」。后者用括号来划定多选结构的范围(正常情况下,括号也是元字符)。请注意,「 gr[a|e]y」不符合我们的要求——在这里, ‘|’只是一个和「 a」与「 e」一样的普通字符。
对表达式「 gr(a|e)y」来说, 括号是必须的, 因为如果没有括号,「 gra|ey」的意思就成了“ 「 gra」或者「 ey」”, 而这不符合我们的要求。 多选结构可以包括很多字符,但不能超越括号的界限。
「 gr[ea]y」与「 gr(a|e)y」的例子可能会让人觉得多选结构与字符组没太大的区别, 但是请留神不要混淆这两个概念。一个字符组只能匹配目标文本中的单个字符, 而每个多选结构自身都可能是完整的正则表达式,都可以匹配任意长度的文本。

  • 忽略大小写:“-i”

egrep的命令行参数“-i”,告诉 egrep在比较时忽略大小写, 也就是进行不区分大小写的匹配,这样就能忽略大小写字母的差异。
该功能不是正则表达式语言的一部分,却是许多工具软件提供的有用的相关特性。egrep的命令行参数“-i”表示进行忽略大小写的匹配。把-i写在正则表达式之前。

  • 单词分界符:「 \<」和「 \>」

某些版本的egrep对单词识别提供了有限的支持:也就是单词分界符(单词开头和结束的位置)的匹配。如果你的egrep支持“元字符序列( metasequences) ” 「 \<」和「 \>」, 就可以使用它们来匹配单词分界的位置。 可以把它们想象为单词版本的「 ^」和「 $」, 分别用来匹配单词的开头和结束位置。
就像作为行锚点的脱字符和美元符一样, 他们锚定了正则表达式的其他部分, 但在匹配过程中并不对应到任何字符。
表达式「 \<cat\>」的意思是“匹配单词的开头位置,然后是c–a–t这3个字母, 然后是单词的结束位置”。 更直接点说就是“匹配cat这个单词”。 如果读者愿意,也可以用「 \<cat」和「 cat\>」来匹配以 cat开头和结束的单词。
请注意,「 <」和「 >」本身并不是元字符——只有当它们与斜线结合起来的时候, 整个序列才具有特殊意义。 这就是我称其为“元字符序列”的原因。 重要的是它们的特殊意义, 而不是字符的个数,所以我说的“元字符”和“元(字符)序列”大多数时候是等价的。

  • 可选项元素:「 ? 」

现在来看color和colour的匹配。它们的区别在于,后面的单词比前面的多一个 u,我们可以用「 colou?r」来解决这个问题。 元字符「 ? 」( 也就是问号) 代表可选项。 把它加在一个字符的后面,就表示此处容许出现这个字符,不过它的出现并非匹配成功的必要条件。「 u?」这个元字符与我们之前看到的元字符都不相同,它只作用于之前紧邻的元素。因此,「 colou?r」的意思是:「 c」,然后是「 o」,然后是「 l」,然后是「 o」,然后是「 u?」,最后是「 r」。
可以把「 4th|4」简化为「 4(th)?」。 我们看到, 现在「 ?」作用的元素是整个括号了。 号内的表达式可以任意复杂, 但是“从括号外来看”它们是个整体。 界定「 ?」的作用对象 ( 还可以划定我即将介绍的其他类似元字符的作用对象)是括号的主要用途之一。

  • 重复量词:「 +」、「 *」

「 +」( 加号) 和「 *」( 星号) 的作用与问号类似。 元字符「 +」表示“之前紧邻的元素出现一次或多次”, 而「 *」表示“之前紧邻的元素出现任意多次, 或者不出现”。 换种说法就是,「 …*」表示“匹配尽可能多的次数, 如果实在无法匹配, 也不要紧”。「 …+」的意思与之类似, 也是匹配尽可能多的次数,但如果连一次匹配都无法完成,就报告失败。
问号、加号和星号这3个元字符,统称为量词( quantifiers),因为它们限定了所作用元素的匹配次数。与
「…?」一样, 正则表达式中的「 …*」也是永远不会匹配失败的, 区别只在于它们的匹配结果。而「 …+」在无法进行任何一次匹配时,会报告匹配失败。
个字符组是一个“元素”( unit),所以它可以直接加加号、星号等,而不需要用括号。

  • 区间量词:「 …{min, max}」

某些版本的egrep能够使用元字符序列来自定义重现次数的区间:「 …{min, max}」。 这称为“区间量词( interval quantifier) ”。例如,「 …{3,12}」能够容许的重现次数在3到12之间。有人可能会用「 [a-zA-Z]{1,5}」来匹配美国的股票代码( 1到5个字母)。问号对应的区间量词是{0,1}。
支持区间表示法的egrep的版本并不多,但有许多另外的工具支持它。

  • 括号及反向引用

到目前为止, 我们已经见过括号的两种用途: 限制多选项的范围; 将若干字符组合为一个单元,受问号或星号之类量词的作用。现在我要介绍括号的另一种用途,虽然它在egrep中并不常见(不过流行的GNU版本确实支持这一功能),但在其他工具软件中很常见。在许多流派( flavor)的正则表达式中,括号能够“记住”它们包含的子表达式匹配的文本。反向引用是正则表达式的特性之一, 它容许我们匹配与表达式先前部分匹配的同样的文本。

在支持反向引用的工具软件中, 括号能够“记忆”其中的子表达式匹配的文本, 不论这些文本是什么,元字符序列「 \1」都能记住它们。当然, 在一个表达式中我们可以使用多个括号。 再用「 \1」、「 \2」、「 \3」等来表示第一、 第二、第三组括号匹配的文本。括号是按照开括号‘(’从左至右的出现顺序进行的,所以「 ([a-z])([0-9])\1\2」中的「 \1」代表「 [a-z]」匹配的内容,而「 \2」代表「 [0-9]」匹配的内容。


注:
什么「 q[^u]」无法匹配‘Iraq’的行?
正则表达式要求q之后紧跟一个u以外的字符, 这就排除了q处在行尾的情况。 通常来说, 文本行的结尾都有一个换行字符, 但是egrep会在检查正则表达式之前把这些换行符去掉,所以在行尾的q之后,没有能够匹配u以外的字符。

posted on 2015-12-29 19:07  marvin.li  阅读(263)  评论(0编辑  收藏  举报

导航