正则表达式入门

内容:如题
前置技能:None
参考教程:30分钟正则入门

前言

最近喜欢各种入门,这里入门一下正则表达式。字数很少比较水。

字符串可以说是编程是遇到的最多的一种数据结构,也是最简单的数据结构,对字符串操作的需求可谓无处不在。给人阅读的文本可以看做字符串,内存中存储的特定编码序列可以看做字符串,一个网页的html文本是字符串,浏览器对html文本解析的过程是字符串处理,无论是编译型语言还是解释型语言,编译和解释的过程都可以看做字符串处理。字符串操作重要性不言而喻。而在字符串中一种很常见的操作就是字符串的匹配。编写程序去处理特定的需要匹配的字符串可以做到,但耗时耗力,且代码不具有重用性。所以我们需要正则表达式。

正则表达式(Regular Expression)是一种匹配规则,用来匹配你想要的各种形式的字符串。规则有了还不行,还需要一个正则引擎来支持它,正则引擎可以看做一种编译器,实现需要用到编译原理的知识,支持语法越多越复杂,这里不讨论(有时间实现,挖坑,以后填)。

在Shell中我们常用*来表示匹配所有项,比如ls *.v表示列出该目录下所有.v文件。*是正则的语法,能这样用是因为Shell部分支持正则表达式。*也称为通配符。

正则表达式是难于读写的,所以需要对其正确性进行测试,可以使用上面那篇教程的作者写的一个正则表达式测试器,也可以使用这个在线正则表达式测试器

正则语法

元字符

首先如果想要匹配特定字符串,直接使用该字符串即可。

另外一些匹配字符或者位置的元字符:

  • \b 匹配一个位置,单词的开头或者结尾
  • . 匹配除了换行符以外的任何字符
  • \d 匹配一个数字,即0到9
  • \s 匹配空白符,包括空格、制表符、换行等
  • \w 匹配一个字母数字下划线或者汉字等
  • ^ 匹配字符串开始的位置
  • $ 匹配字符串结尾的位置

其中\b ^ $ 匹配位置而不是字符,就是说他们不匹配为一个字符,即不占一个字符的位置。

重复

代表重复的限定符不匹配字符,仅代表限定符前的字符可以重复的次数。

  • * 指定*前面的内容可以使用任意次(0次或者多次)
  • +*类似,不过是1次或者多次
  • ? 重复0或者1次
  • {n} 重复n次
  • {n,} 重复n次或者更多次
  • {n,m} 重复n到m次

eg: ^[1-9]\d{4,9}$匹配一个5到10位的不以0开头的数字串,可以是QQ号

但是如果要匹配上面这些已经有特殊意义的字符呢?当然是转义了:\* \. \- \\

字符类

使用[aeiou]表示aeiou中的任何一个字符。
[0-9]就等同于\d。这里可以使用-表示范围。

分枝条件

使用|表示或者。\d|[a-zA-Z]匹配字母或者数字。

分组

使用()进行分组,每个分组也称为子表达式。可以对每个子表达式使用上面的表示重复的语法。
如果要匹配(或者),则需要转义\( \)[] {}同理。

eg:匹配一个IP地址 -> ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) ,其中(2[0-4]\d|25[0-5]|[01]?\d\d?)表示0到255。

反义

能匹配符合某种模式的,肯定也需要匹配不满足某种模式的。

  • \W 匹配任意不是字母数字下划线汉字的字符
  • \S 匹配不是空白符的字符
  • \D 匹配非数字字符
  • \B 匹配非单词开始和结尾的任何位置
  • [^X] 匹配除X以外的任何字符
  • [^aeiou] 匹配除aeiou外的所以字符

后向引用

使用()指定子表达式时,每个分组会自动拥有一个组号,从1开始依次增加。后向引用可以重复使用前面某个分组匹配的文本。使用\k表示匹配编号为k的分组捕获的内容。

eg:匹配重复单词 \b(\w+)\b\s+\1\b ,注意是匹配重复单词,而不是两个单词,即是第一个分组捕获了一个单词并被\1引用。

另外可以自己指定组名,使用语法 (?<Word>\w+) 或者 (?'Word'\w+) 则组名指定为 Word,引用该分组捕获的内容则使用\k<Word>。上面的例子:\b(?<Word>\w+)\b\s+\k<Word>\b

(?:exp) 匹配exp,但不捕获文本,也不分配组号。

零宽断言

  • (?=exp),零宽度正预测先行断言,断言自身出现的位置的后面能匹配表达式exp,即匹配表达式exp前面的位置。
  • (?<=exp),零宽度正回顾后发断言,匹配表达式exp后面的位置
  • (?!exp),零宽度负预测先行断言,匹配后面不是exp的位置
  • (?<!exp),宽度正回顾后发断言,匹配前面不是exp的位置

忽略它们的名字,语法均是()中以?开头,然后有<代表后面的位置,没有则代表前面,=代表匹配,!代表不匹配。注意它们都匹配位置而不是字符。

另外一个与()相关的语法是注释:(?#comment)

贪婪与懒惰

上面的重复如* {n,m}等蕴含着一个问题。即是使用a.*b来匹配字符串aabab是得到aab还是aabab。答案是aabab,因为默认情况下是贪婪匹配,即在匹配的情况下尽可能多重复。

在重复匹配的语法后面加上一个?可以将其变为懒惰匹配,即尽可能少重复。语法:*? +? ?? {n,}? {n,m}?

处理选项

如果语法太死的话似乎会给人不够灵活的感觉。在.Net下,有一些处理选型可以改变处理正则的方式,比如在某些时候需要忽略大小写是很必要的。详见:正则表达式选项

转义字符

匹配上面用到的特殊字符时都需要转义,另外ASCII编码本身定义的转义字符也是支持的。详见:正则表达式中的字符转义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值