《正则表达式必知必会》Part 1

最近正在做数据提取和清洗相关的工作,碰到很多问题可以使用正则表达式很好的解决。之前一直对正则表达式没有系统的学习大多是一知半解,正好趁这次机会对正则表达式做一个较为全面一些的了解。因为是应用实战为主,并没有打算花太多的时间在上面,因此选择了一本比较薄的类似于速查手册型的书《正则表达式必知必会》。这本书现在有更新的(修订版),但是找不到免费的电子版,抱着先学习的心态找了一个第一版的电子版花了一个晚上给看了,在这里对用一些要点做一些记录,纸质书下次再支持作者吧。

《正则表达式必知必会》·正则表达式入门

正则表达式(regular expression,简称regEx)已经出现了很多年,对于各种复杂的文本处理工作来说可以说是一种为了强大的武器,而且它可以在几乎所有的程序设计语言和操作系统上使用。正则表达式有两种基本用途:一种是查找特定的信息(搜索),另一种是查找并编辑特定的信息(替换)。

regEx可以说是一种迷你的语言,语法是最容易掌握的部分,真正的挑战是学会如何灵活运用那些语法把实际问题分解为一系列正则表达式并最终解决,它不存在所谓的正则表达式程序,既不是可以直接运行的应用程序,也不是可以下载的软件,但在绝大多数的编程语言和各种开发环境regEx都已被实现。regEx在不同的应用程序/语言种语法和功能往往会有一定的区别,但最基本的核心使用方法和功能大体都是一致的,如果遇到兼容问题可以查阅相关的文档。

§ 匹配单个字符

  • 匹配纯文本

正则表达式可以包含纯文本(甚至只包含纯文本),同时需要区分大小写,不过大多数regEx的实现都支持不区分大小写的匹配(e.g. Benben )。当存在多个匹配结果的时候各种不同的实现也提供了把所有匹配结果全部找出来的机制,通常返回一个数组或者其他专用格式。

  • 匹配任意字符

静态纯文本的匹配体现不出regEx真正的威力,它可以使用 . 字符(英文句号)去匹配任意一个单个的字符。

  • 匹配特殊字符

. 字符在regEx中有特殊的含义,如果正好需要匹配这个字符呢?就需要想办法告诉表达式你需要的是该字符本身而不是其在表达式里的特殊含义,为此你需要在该字符前面加上一个 \ 字符(反斜杠)对其进行转义。\ 是一个元字符(metacharacter, 表示这个字符有特殊含义,而不是字符本身的含义)。 例如,.a.\.doc 将匹配前三字母中第二个为 a 且以 .doc 结尾的字符串。

正则表达式经常被简称为模式(Pattern),它们其实是一些由字符构成的字符串,这些字符可以是普通字符(纯文本)或元字符(有特殊含义的特殊字符)。. 可以匹配任何字符,\ 用来对字符进行转义,在正则表达式里有特殊含义的字符序列总是以\ 字符开头。

§ 匹配一组字符

  • 匹配多个字符中的某一个

如果你只想匹配ns 两个字符,在正则表达式中可以使用元字符[] 来定义一个字符集合。在使用[] 定义的字符集合里,这两个字符之间的所有字符都是该集合的组成部分,字符集合的匹配结果是能够与该集合里的任意_一个_成员相匹配的文本。例如,[ns]a 将匹配nasa ,这也可以用来同时匹配大小写字母。

  • 利用字符集合区间

当你需要匹配0到9的数字的时候可以使用[0123456789] ,但如果要匹配的是某一个字母呢?不可能将所有的字母都列出来,此时就会频繁用到一些字符区间如[0-9][a-z][A-Z] 等等。例如,[a-f0-7] 等价于[abcdef01234567] ,某一个RGB色值可以是#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]

  • 取非匹配

字符集合通常用来指定一组必须匹配其中之一的字符。但在某一些场合,我们需要反过来做,给出一组不需要得到的字符。即_除了字符集合里的字符,其他字符都可以匹配_。用元字符^ 来表明你相对严格字符集合进行取非匹配,这与逻辑非运算很相似,只是这里的操作数是字符集合。例如,[ns]a[^0-9] 将不匹配结尾为数字的字符串。

元字符[] 用来定义一个字符的集合,其含义是必须匹配该集合里的字符之一。定义一个字符集合的具体做法有两种:一是把所有的字符都列举出来;二是利用元字符- 以字符全歼的方式给出。字符集合可以用元字符^ 来求非。这将把给定的字符集合内所有字符和字符区间强行排除在匹配操作以外,即除了该字符集合里的字符,其他字符都将被匹配。

§ 使用元字符

  • 对特殊字符进行转义

元字符是一些在正则表达式中有着特殊含义的字符,前面介绍用到的英文句号. 和左右方括号[ ] 都是元字符。因为元字符在表达式里的特殊含义,所以这些字符就无法用来代表他们本身。我们通过在元字符前面加上一个反斜杠\ 来对相关的字符进行转义。例如,我们要匹配数组标识Array[0-9] ,那么正则表达式为Arrary\[[0-9]\] 。同时,由于对元字符进行转义需要用到反斜杠,这意味着反斜杠也是一个元字符,所以在匹配\ 的时候请一定记住使用\\

  • 匹配空白字符

在进行正则表达式搜索的时候,我们经常雨打需要对原始文本里面的非打印空白字符进行匹配的情况。例如我们可能要把所有的制表符或者换行符找出来,这一类的字符很难直接输入到正则表达式里面,所以需要使用下面列出的特殊元字符来进行输入。

[\b] :回退(并删除)一个字符(Backspace键)

\f :换页符

\b :换行符

\r :回车符

\t :制表符(Tab键)

\v :垂直制表符

TIPS:\r\n 是Windows所使用的文本行结束标签,而Linux和Unix系统只是用一个换行符\n 来结束一个文本行。

  • 匹配特定的字符类别

字符集合是最常见的匹配形式,而一些常见的字符集合可以使用特殊元字符来替代,它们并不是必不可少的东西,但是使用它们构造的正则表达式简明易懂,在实践中很有用。

匹配数字(与非数字):\d 匹配任何一个数字字符(等价于[0-9] ); \D 匹配任何一个非数字(等价于[^0-9] )。

匹配字母和数字(与非字母和数字):\w 匹配任何一个字母数字字符(大小写均可)或下划线(等价于[a-zA-Z0-9_] );\W 匹配任何一个非字母数字或非下划线字符(等价于[^a-zA-Z0-9_] )。

匹配空白字符(与非空白字符):\s 匹配任何一个空白字符(等价于[\f\n\r\t\v] );\S 匹配任何一个非空白字符(等价于[^\f\n\r\t\v] )。

匹配十六进制或者八进制数值:在正则表达式中,十六进制数值要用前缀\x 来给出。比如说,\x0A 对应于ASCII字符10 (换行符),其效果等价于\n 。八进制数值则要用前缀\0 来给出,数值本身可以是两位或者三位数字。比如说,\011 对应于ASCII字符9 (制表符),等价于\t

  • POSIX字符类

POSIX字符类是许多(但不是所有)正则表达式实现都支持的一种简写形式,更多支持的字符类可以在搜索引擎中查找到。例如,[:alpha:] 匹配任何一个字母(等价于[a-zA-Z] );[:xdigit:] 匹配任何一个十六进制数字(等价于[a-fA-F0-9] )。

元字符本身的匹配需要使用到转义字符\ ,同时可以使用一些特殊的元字符来匹配一个字符集合或字符类(数字、字母数字字符等等),这些简短的元字符和POSIX字符类可以用来简化正则表达式模式。

0%