文章目录
  1. 1. 正则表达式初始
    1. 1.1. 元字符
    2. 1.2. 分枝条件
    3. 1.3. 字符类
    4. 1.4. 分组
    5. 1.5. 反义
    6. 1.6. 后向引用
  2. 2. 零宽断言
  3. 3. 负向零宽断言
  4. 4. 注释
  5. 5. 贪婪与懒惰贪婪与懒惰
  6. 6. 平衡组/递归匹配
  7. 7. 正则表达式匹配HTML标签或标记
  8. 8. 学习参考

正则表达式初始

元字符

  • \b 是正则表达式规定的一个特殊代码(好吧,某些人叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处
1
\bhi\b.*\bLucy\b
  • . 是另一个元字符,匹配除了换行符以外的任意字符。
  • *同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定前边的内容可以连续重复使用任意次以使整个表达式得到匹配。因此,. 连在一起就意味着任意数量的不包含换行的字符。

换行符就是’\n’,ASCII编码为10(十六进制0x0A)的字符。

  • \d是个新的元字符,匹配一位数字(0,或1,或2,或……)
1
0\d{2}-\d{8}

这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配2次(8次)。

表1.常用的元字符

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

表2.常用的限定符 (都是修饰前面的元字符)

代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次 ?前面的元字符重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

分枝条件

正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开

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

字符类

要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办?你只需要在方括号里列出它们就行了,像[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(.或?或!)。

分组

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

描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

反义

有时需要查找不属于某个能简单定义的字符类的字符

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

例子:\S+匹配不包含空白符的字符串。

后向引用

后向引用用于重复搜索前面某个分组匹配的文本。

语法

(?<Word>\w+) (或者把尖括号换成’也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了

零宽断言

接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),

(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分)

(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分)

负向零宽断言

奇葩名字啥意思
确保某个字符没有出现,但并不想去匹配它

\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b

零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp

(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字

注释

1 小括号的另一种用途是通过语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)
2 忽略模式里的空白符

(?<= # 断言要匹配的文本的前缀
<(\w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签)
) # 前缀结束
.* # 匹配任意文本
(?= # 断言要匹配的文本的后缀
<\/\1> # 查找尖括号括起来的内容:前面是一个”/“,后面是先前捕获的标签
) # 后缀结束

贪婪与懒惰贪婪与懒惰

平衡组/递归匹配

语法构造

  • (?’group’) 把捕获的内容命名为group,并压入堆栈(Stack)
  • (?’-group’) 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
  • (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
  • (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

正则表达式匹配HTML标签或标记

详情见http://c.biancheng.net/cpp/html/1402.html

学习参考

文章目录
  1. 1. 正则表达式初始
    1. 1.1. 元字符
    2. 1.2. 分枝条件
    3. 1.3. 字符类
    4. 1.4. 分组
    5. 1.5. 反义
    6. 1.6. 后向引用
  2. 2. 零宽断言
  3. 3. 负向零宽断言
  4. 4. 注释
  5. 5. 贪婪与懒惰贪婪与懒惰
  6. 6. 平衡组/递归匹配
  7. 7. 正则表达式匹配HTML标签或标记
  8. 8. 学习参考