正则表达式学习笔记

正则表达式是一种强大的工具,虽然看起来非常复杂,实际上遵循着非常严格和简单的规则。通过并不太长时间的学习,你就能了解如何写出适合自己使用的正则表达式。
这里,是我在学习正则表达式的时候,记录的一些学习心得。入门我是通过网上非常有名的这篇<30分钟正则表达式入门>来完成学习的。在记录完笔记后,在各种应用场合,不断的尝试写出适合的正则表达式,我非常容易的掌握到正则表达式的规则。希望你也能抽出半天时间(30分钟当然是不可能的),就可以完成正则表达式这一强大工具的学习。
原文是针对C#正则技巧的内容,和OC应稍有区别,但入门知识基本相同。OC和大多数其他语言,不支持C#中的平衡组等复杂用法
Mac上正则表达式推荐工具可以使用:Reggy来做验证和测试,免费开源好用。

基本概念

hi
– 匹配所有等于hi的字符(不区分大小写)

bhib
– b为元字符(metacharacter),代表一个单词的开头和结尾(分界处-一般是空格、标点、换行).
– 精确匹配hi单词

bhib.*bLucyb
– 查找hi和Lucy中间的内容
.代表除换行符以外任意字符
*代表数量,任意次数
.*代表任意数量不包含换行符的字符

0dd-dddddddd 或者 0d{2}-d{8}
– 以0开头,两位数字后有-连字号,后面跟8位数字
d是匹配数字,-不是元字符,只是普通字符
{2}由大括号包含的数字,意思是前面的元字符必须匹配几次
{2,4}是指匹配不少于2次,不多于4次

其他元字符:

  • s 匹配任意空白符,包括空格,制表[tab],换行、中文全角空格
  • w 匹配字符或下划线或汉字
  • + +号也是匹配数量,但不同与*+是必须重复匹配1次以上(*可以匹配0次),?是重复0次或一次
元字符 说明
* 重复零次或多次
+ 重复一次或多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复不少于n次,不多于m次
  • ^$ 匹配查找字符串的开头和结尾,如果是增加了处理多行的选项,^$意思是匹配一行的开始和结束
  • 是转义,会将后面的特殊元字符,转为普通字符(*、+、^、$、.等)

字符类

  • []包含起来的内容,即为需要匹配的内容,注意[``]里的.?!不需要加转义
  • []内的-,代表从字符集起始到结束,例如[0-9]d意思一样,[a-z0-9A-Z]则代表所有英文字母和数字集合
  • (?0d{2}[)-]?d{8} :
    • (是转义(,(?代表首部出现(一次或零次
    • d{2}匹配0出现之后有2位数字
    • 后面的[)-]是指后面可以有)和-,[)-]?代表)和-可以出现一次或零次
    • d{8}为最后8位数字

分支条件

  • 有几种规则,满足任意一种即为匹配
  • |隔开的规则,即为分支规则
  • 0d{2}-d{8}|0d{3}-d{7}:两种规则0d{2}-d{8}0d{3}-d{7}满足任意一条即可(3位数字-8位数字或4位数字-7位数字)
  • 分支要注意各条件的顺序,匹配时从左至右匹配,如果满足某个分技,则不再管另一分支
    • d{5}-d{4}|d{5}d{5}|d{5}-d{4}两个正则不一致
      • 前者是匹配美国邮编的标准(前5后4共9位数字,或者是5位数字)
      • 后面只匹配5位的数字

分组

  • 使用()包围的条件,是为一组
  • 可以对组(或称子表达式)使用后缀元字符条件,来限定这一分组匹配重复次数等

反义

  • 查找非规定范围以外的字符
  • 基本上小写是正常,大写是反义
  • 反义排除的只是字母列表,无关顺序,即[^abc],会排队a,b,c三个字母,而不是排队abc顺序的三个字母。
元字符 说明
W 任意非字母、数字、下划线、汉字的字符
S 任意非空白符的字符
D 任意非数字的字符
B 任意非开头和结束的位置
[^x] 任意非x的字符
[^abcd] 任意非abcd的字符

后向引用

  • 使用小括号()包围起来的分组,会自动拥有一个从左自右的从1开始的编号
  • 正则会先把匹配分组的结果捕获出来,以相应编号来组织,可以用编号的形式来对这相对应的结果进行进一步处理

b(w+)bs+1b 匹配重复出现的单词(叠词)
b(w+)b的结果会被捕获到编号为1的分组中
s一个空格
1 引用编号1分组的结果
即寻找一个单词空格后,再重复一次的单词,例Go Go

  • 在括号开始的地方,用?<名字>或者?'名字'可以自定义分组名.
  • 自定义的分组名,使用k<名字>来调用
  • (?:)如果在括号开始用?:的话,即表示这一括号即不保存捕获的结果,也不给这一括号分配组号

零宽断言

  • 零宽断言是指查找某些内容前后的文本,但不包含这些内容本身。
  • b,^,$这几个关键字,其实也是一种零宽断言
  • 零宽断言主要用来查找
    • (?=关键词表达式): (零宽度正预测先行断言)断言关键词出现的位置后面能匹配表达式

      bw+(?=ingb) 匹配以ing结尾的单词前半部分 : being 会匹配出be

    • (?<=关键词表达式)(零宽度正回顾后发断言):断言关键词出现的位置前面能匹配表达式

      (?<=bre)w+b 匹配以re开头的单词的后半部分: replay 会匹配出play

    • (?!关键词表达式)(零宽度负预测先行断言):断言关键词出现的位置后面不能匹配表达式

      bw*q[^u]w*b:匹配q后面不包含u的单词,但这一正则无法筛除最后一位是q的情况,则”Iraq fighting”也会被匹配。因为[^u]占用了一个字符位。
      bw*q(?!u)w*b:使用零宽负预测先行断言,即可解决这种问题,它只匹配位置,并不消费(使用)任何位置。

    • (?<!关键词表达式)(零宽度负回顾后发断言):断言关键词出现的位置前面不能匹配表达式

贪婪与懒惰(最大匹配和最小匹配)

  • 默认是贪婪匹配:即在匹配条件的情况下,尽可能多的匹配字符。
  • 在条件后加上?即可显式声明为懒惰匹配,即尽可能少的匹配字符

aabab 字串中,按a.*b,默认会匹配整个字符串
a.*?b:则只匹配aab和ab

处理选项

  • 大小写
  • 多行模式:使^$匹配行首和行尾,而不仅仅是整个字符串的开头和结尾。
  • 单行模式:更改.的含义,使.代表所有字符(包含换行符)
  • 忽略空白:忽略表达式中的非转义空白,并启用#代表注释
  • 显示捕获:仅显示捕获被声明的组,而不是给所有括号内的组默认命名(1~n)

平衡(对称)/递归匹配

  • 需要匹配成对出现的内容
  • (?'标签名'条件) 满足条件,则把标签名入栈
  • (?'-标签名'条件) 若满足条件,标签名出栈,如果栈为空,匹配失败
  • (?(标签名)yes|no) 如果标签名的栈中有内容,则匹配yes规则,否则匹配no规则
  • (?!) 总是失败的匹配,用来在平衡递归匹配中,中断匹配条件

注释

  • (?#注释):注释最好启用处理选项中的”忽略模式里的空白符“设置(C#)

1 Comment

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注