正则表达式入门

正则表达式入门

Posted by 刘一凡 on December 27, 2016

正则表达式30分钟入门教程

入门

元字符

下面是常用元字符:

代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意空白符
\d 匹配数字
\b 匹配单词的开始或者结束
^ 匹配字符串的开始
$ 匹配字符串的结束

重复

下面是正则表达式中所有的限定符(指定数量的代码):

代码 说明
* 重复0次或者多次
+ 重复1次或者多次
? 重复0次或者1次
{n} 重复n次
{n,} 重复n次或者多次
{n,m} 重复n到m次

字符类

[] 可以指定一个字符范围,比如 [aeiou],表示匹配一个英文元音字母。[0-9] 代表的含义与 \d 就是完全一致的:一位数字。

一个复杂的表达式L \(?0\d{2}[) -]?\d{8}

这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行分析:首先是一个转义字符 \(,它可能出现 0 次或者 1次 (?),然后是一个 0,后面跟着两个数字 (\d{2}),然后是 (- 或 空格 中的一个,它出现一次或者不出现,最后是8个数字 (\d{8})。

分支条件

前面的表达式,也可以匹配 010)12345678 这样错误的表达式。我们可以使用分支条件来解决这个问题。

分支条件指的是有几种规则,如果满足一种规则就应该当成匹配,具体是使用 | 分隔符把不同的规则分割开。

比如,0\d{2}-\d{8}|0\d{3}-\d{7} 这个表达式能匹配两种以连字符分割的电话号码:一种是3位区号,一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。

分组

() 用小括号来指定子表达式(也叫分组)。

反义

常用的反义代码:

代码/语法 说明
\W 匹配不是字母,数字,下划线,汉字的字符
\S 匹配不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或者结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本可以在表达式或其他程序中进一步操作。默认情况,每个分组都自动拥有一个组号,从左到右,第一个为 1,第二个为 2……

后向引用用于重复搜索前面某个分组匹配的文本。例如 \1 代表分组1匹配的内容。

常用的分组语法:

分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
  (?exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
  (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
  (?<=exp) 匹配exp后面的位置
  (?!exp) 匹配后面跟的不是exp的位置
  (?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,通常的行为是(在整个表达式能够得到匹配的前提下)匹配尽可能多的字符串。

以这个表达式为例 a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索 aabab 的话,它会匹配整个字符串 aabab,这被称为贪婪匹配。

有时候更需要 懒惰 匹配,也就是匹配 尽可能少 的字符。前面给出的限定符都可以被转化为 懒惰匹配,只要在它后面加上一个问号 ?。这样 .*? 就意味着 “匹配任意数量的重复,但是在能使整个匹配成功的前提下 使用最少的重复”。

a.*?b 匹配最短的,以 a 开始,以 b 结束的字符串。如果把它应用于 aabab 的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

懒惰限定符:

代码/语法 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复