实例攻克正则表达式

[TOC]

零、什么是正则表达式?

正则表达式是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。

一个正则表达式是一种从左到右匹配主体字符串的模式。 “Regular expression”这个词比较拗口,我们常使用缩写的术语“regex”或“regexp”。 正则表达式可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等。

想象你正在写一个应用,然后你想设定一个用户命名的规则,让用户名包含字符、数字、下划线和连字符,以及限制字符的个数,好让名字看起来没那么丑。 我们使用以下正则表达式来验证一个用户名:

以上的正则表达式可以接受 john_doejo-hn_doejohn12_as。 但不匹配Jo,因为它包含了大写的字母而且太短了。

具体到正式的应用场景中时,有的语言需要对特殊字符如换行符\n加转义字符\,而有的语言则匹配原始字符(如Python),即直接匹配r'匹配内容'

接下来,就通过一些简单的实例介绍正则表达式的一些用法。
正则表达式测试网站:https://regex101.com

# 原始例句
Compromise where you can.But where you can't, don't.\r\n
Even if everyone is telling you that something wrong is something right,Even if the whole world is telling you to move.
It is your duty, to plant yourself like a tree,look at them in the eyes and say,"no......you move."
该让步时让步,不该让步时决不退让。
即使每个人都告诉你措的东西是对的,即使整个世界都逼你让开。
你需要做的是坚定信念,看着他们的眼睛告诉他们:“不,你们让开”。
3.1415926535 89793 23846 26433 83279 50288 41971 69399 37510 58209 74944 59230 78164 06286 20899 86280 34825 34211 70679

一、基本匹配

正则表达式其实就是在执行搜索时的格式,它由一些字母和数字组合而成。 例如:一个正则表达式 the,它表示一个规则:由字母t开始,接着是h,再接着是e。数字、汉字同理。

注意正则表达式是大小写敏感的,所以The不会匹配the

二、元字符

正则表达式主要依赖于元字符。 元字符不代表他们本身的字面意思,他们都有特殊的含义。一些元字符写在方括号中的时候有一些特殊的意思。以下是一些元字符的介绍:

1、 .点运算符

.匹配换行符之外的任意单个字符,但不匹配。 例如,表达式.er匹配一个任意字符后面跟着是er的字符串。

2、[]字符集

字符集也叫做字符类。 []方括号用来指定一个字符集。

(1)[ab]=[ba]无序性

  • 【规则1】在方括号中的字符集不关心顺序。
  • 【例1】表达式[hl]ing就同时匹配到了tellingsomething

(2)[A-Z][0-9]范围字符

  • 【规则2】在方括号中使用连字符来指定字符集的范围。
  • 【例2】表达式[A-Z][a-z]就匹配到了所有包含连续的大写字母和小写字母的字符串。

(3)[,.]方括号里内容保留

  • 【规则3】方括号的逗号、句号就表示逗号、句号。
  • 【例3】 表达式 t[,.] 就同时匹配到了 can't, don't. right,字符串

(4)^否定字符集

  • 【规则4】否定字符集: ^。它用在一个方括号的开头的时候,它表示这个字符集是否定的。
  • 【例4】表达式 [^t][,.] 就同时匹配到了 除了前面是t的所有带,和.标点的字符串。

3、重复次数

后面跟着元字符 +* or ? 的,用来指定匹配子模式的次数。 这些元字符在不同的情况下有着不同的意思。

(1)*重复大于等于0次

*号匹配 在*之前的字符出现大于等于0次。

  • 【例1】*和表示匹配空格的符号\s连起来用。如表达式 \s*y 匹配以0或更多个空格开头、以y结尾的字符。
  • 【例2】表达式[a-z]* 匹配一个行中所有以小写字母开头的字符串。
  • 【例3】*字符和.字符搭配可以匹配所有的字符.*

(2)+重复大于等于1次

+号匹配+号之前的字符出现大于等于1次。

如上面文字中\s*让就可以匹配到内容,\s+让就无法匹配到内容。

(3)?重复0次或1次

?号匹配?号之前的字符出现0或1次。

例如,表达式 \s?23 匹配字符串 23\s23

(4){}重复指定次数(范围)

{} 用来限定一个或一组字符可以重复出现的次数。

  • 【例1】重复6-7次:表达式 [0-9]{6,7} 匹配最少 6 位最多 7 位 0~9 的数字。

  • 【例2】重复最少5次:表达式[0-9]{2,} 匹配至少 5 位 0~9 的数字。
  • 【例3】重复固定8次:表达式[0-9]{8} 匹配 8 位数字。

4、| 或运算符

或运算符就表示或,用作判断条件。不解释。

5、 (...) 特征标群

特征标群是一组写在 (...) 中的子模式。(...) 中包含的内容将会被看成一个整体。

  • 【例1】表达式 t(el)* 匹配以t开头的连续出现 0 或更多个 el。如果没有使用 (...) ,那么表达式 tel* 将匹配以te开头的连续出现 0 或更多个 l
  • 【例2】将上面的*换成{}也同理。如:表达式 t(el){0,2} 匹配以t开头的连续出现 0到2 个 el。如果没有使用 (...) ,那么表达式 tel{0,2} 将匹配以te开头的连续出现 0到2 个 l
  • 【例3】还可以在 () 中用或字符 | 表示或。例如,(d|every|r)on 匹配 doneveryonron.

6、\转码特殊字符

类似于编程语言中的转义字符,在 { } [ ] / \ + * . $ ^ | ? 这些特殊字符之前加\用于匹配这些特殊字符本身。

例如 . 是用来匹配除换行符外的所有字符的。如果想要匹配句子中的 . 则要写成 \.

7、^$锚点,检查匹配开头结尾

(1) ^ 号检查匹配开头

^ 用来检查匹配的字符串是否在所匹配字符串的开头。

例如,使用表达式 ^Compr 会匹配开头的Compr

(2) $ 号检查匹配结尾

同理于 ^ 号,$ 号用来匹配字符是否是最后一个。

例如,9$ 就只匹配到了以 9 结尾的字符串,而不匹配其他的 9。

三、简写字符集

正则表达式提供一些常用的字符集简写。如下:

简写描述
.除换行符外的所有字符
\w匹配所有字母数字,等同于 [a-zA-Z0-9_]
\W匹配所有非字母数字,即符号,等同于: [^\w]
\d匹配数字: [0-9]
\D匹配非数字: [^\d]
\s匹配所有空格字符,等同于: [\t\n\f\r\p{Z}]
\S匹配所有非空格字符: [^\s]
\f匹配一个换页符
\n匹配一个换行符
\r匹配一个回车符
\t匹配一个制表符
\v匹配一个垂直制表符
\p匹配 CR/LF(等同于 \r\n),用来匹配 DOS 行终止符

四、筛选结果,带条件匹配

这里原词叫先行断言和后发断言(合称 lookaround),我觉得不太像人话,这里就改了一下。

带条件匹配主要有以下四种类型:

符号描述
?=要匹配的表达式之后需满足某个条件
?!要匹配的表达式之后不能满足某个条件
?<=要匹配的表达式之前需满足某个条件
?<!要匹配的表达式之前不能满足某个条件

1、?=:要匹配的表达式之后需满足某个条件

?=... 正先行断言,使用格式为:(表达式)(?=条件),表示第一部分表达式之后必须跟着 ?=...定义的条件。

例如,表达式 (T|t)he(?=\sfat) 匹配后面紧跟着 (空格)fatThethe ,。

2、?!:要匹配的表达式之后不能满足某个条件

?!... 负先行断言,使用格式为:(表达式)(?!条件),表示第一部分表达式之后不能跟着 ?=...定义的条件。

例如,表达式 (T|t)he(?!\sfat) 匹配 后面不能跟着 (空格)fatThethe

3、?<=:要匹配的表达式之前需满足某个条件

?<= 正后发断言,使用格式为:(?<=条件)(表达式),表示第一部分表达式之前需要跟着满足 ?<=...定义的条件。

例如,表达式 (?<=(T|t)he\s)(fat|mat) 匹配 前面跟着 Thethefatmat

4、?!=:要匹配的表达式之前不能满足某个条件

?!= 负后发断言,使用格式为:(?!=条件)(表达式),表示第一部分表达式之前不能是满足 ?!=...定义的条件。

例如,表达式 (?<!(T|t)he\s)(cat) 匹配 前面不是 Thethecat

五、搜索模式标志

标志也叫模式修正符,因为它可以用来修改表达式的搜索结果。 这些标志可以任意的组合使用,它加在正则表达式/ /之后,也是整个正则表达式的一部分。

标志描述
i忽略大小写。
g全局搜索。
m多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。

1、i忽略大小写 (Case Insensitive)

修饰语 i 用于忽略大小写。

例如,表达式 /The/gi 表示在全局搜索 The,在后面的 i 将其条件修改为忽略大小写,则变成搜索 theTheg 表示全局搜索。

2、g全局搜索 (Global search)

修饰符 g 常用于执行一个全局搜索匹配,即(不仅仅返回第一个匹配的,而是返回全部)。 一般默认执行全局搜索。

例如,表达式 /.(at)/g 表示搜索 任意字符(除了换行)+ at,并返回全部结果。

3、m多行修饰符 (Multiline)

多行修饰符 m 常用于执行一个多行匹配。

像之前介绍的 (^,$) 用于检查格式是否是在待检测字符串全文的开头或结尾。但我们如果想要它在每行的开头和结尾生效,我们需要用到多行修饰符 m

例如,表达式 。$/g 匹配全文以结尾的字符串,而 。$/gm 则匹配每行以结尾的字符串。

六、 ?贪婪匹配与惰性匹配 (Greedy vs lazy matching)

正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。

例如,.*3匹配了”以任意0个或多个字符开头、以3结尾“的字符串,默认匹配最长子串;.*?3匹配了”以任意0个或多个字符开头、以3结尾“的字符串,匹配模式变成了一个个的最短子串。