正则表达式(详解)

文章目录

      • 1、基本匹配
          • 1.1 标志(大小写i/全局g/多行m)
          • 1.2 零宽度断言(前后预查)
          • 1.4 贪婪匹配与惰性匹配 (Greedy vs lazy matching)
      • 2、常见语法(表格)
          • 2.1、元字符
          • 2.2、特殊符号
          • 2.3、扩展表示法
          • 2.4、子表达式
            • 2.4.1 捕获分组
            • 2.4.2 反向引用(匹配叠词)
      • 3、正则工具
          • 3.0、正则教程
          • 3.1、正则大全
          • 3.2、正则解析
          • 3.3、正则练习
          • 3.4、正则工具

1、基本匹配

正则表达式在执行时进行逐个匹配,通常由一些字母和数字组合而成。

例如:正则表达式 The 在匹配时,先匹配字母T,如果T满足匹配借着匹配h,前面都满足再接匹配e。对于正则表达式“sun”的匹配方式,同上。

“The”

The morning sun never lasts a day.

“sun”

The morning sun never lasts a day.

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

“the”

The morning sun never lasts a day.

1.1 标志(大小写i/全局g/多行m)

标志也叫模式修正符,用来决定正则的匹配模式。

标志 英文全称 描述
i insensitive 忽略大小写。
g global 全局搜索。
m multi line 多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。
  • 忽略大小写 (Case Insensitive);
    例如: /abc/i 可以匹配 abc、aBC、Abc 等等
  • 全局搜索 (Global search)
    • 如果不带g,正则过程中字符串从左到右匹配,找到第一个符合条件的即匹配成功。
    • 如果带g,则字符串从左到右,找到每个符合条件的都记录下来,直到字符串结尾位置
    • 表达式 /.(at)/g 表示搜索 任意字符(除了换行与空格)+ at,并返回全部结果。“/.(at)/g” => The fat cat sat on the mat.
  • 多行修饰符 (Multiline)
    • 若存在换行\n并且有开始^或结束$符的情况下,和g一起使用实现全局匹配,
    • 因为存在换行时默认会把换行符作为一个字符任务匹配字符串是个单行,g只匹配第一行,添加m之后实现多行,每个换行符之后就是开始.
    • 比如 (^,$) 用于检查格式是否是在待检测字符串的开头或结尾。但我们如果想要它在每行的开头和结尾生效,我们需要用到多行修饰符 m。

除此之外,还有 x、s、U、a、D、e等标志修正符。

标志 英文全称 描述
x extended 忽略空白字符,可以多行书写,并使用#进行注释说明
s single line 单行模式,此模式下.能匹配任意字符,包括换行符
u unicode 模式字符串被当成UTF-8
U Ungreedy 使量词默认为非贪婪模式
A Anchored 锚点到模式的开始,或最近一次匹配的结束
J Jchanged 允许子模式重复命名,如:(?N1)(?N2)
D Dollar end only $字符仅匹配目标字符串的结尾;没有此选项时,如果最后一个字符是换行符的话$字符也能匹配。
1.2 零宽度断言(前后预查)
  • 零宽度 - 匹配宽度为零
  • 断言 - 满足一定的条件/断言

综上,零宽度断言用于查找一个位置,但不匹配该位置的内容,匹配断言之前的或之后的内容

比如www.baidu.com这个域名。

  • 匹配 www. 之后的内容,使用后发断言
    如图示:因为是零宽度,所以匹配到 www. 到 baidu.com 之间的位置。
    正则表达式(详解)_第1张图片
    此时,我们想得到后面的 baidu.com 只需要再加一个 (.*) 通配若干个任意字符即可。
    正则表达式(详解)_第2张图片
    注:后发断言不等于以 www. 开头,^表示行首,^[w]{3}\. 表示以 www. 开头。

  • 同理, .com 之前的内容,使用先行断言
    正则表达式(详解)_第3张图片
    同理,因为是先行断言,需要在断言成功后,在前面进行匹配,可得到 www.baidu 。
    正则表达式(详解)_第4张图片
    注:后发断言不等于以 .com 结尾,$表示行尾,\.com$ 表示以 .com 结尾。

注意到,因为是零宽度的,因此先行断言和后发断言都不捕获文本 ,仅作为约束。也不会计算到结果分组内。

零宽度断言如下:

符号 描述 示例 匹配项举例
?= 正先行断言-存在 (?=.com) baidu.com或google.com。匹配以.com结尾
?! 负先行断言-排除 (?!.net) baidu.com或baidu.cn。匹配以非.net结尾
?<= 正后发断言-存在 (?<=www) www.baidu.com。匹配以www开头
? 负后发断言-排除 (? www.baidu.com。匹配以非www开头
1.4 贪婪匹配与惰性匹配 (Greedy vs lazy matching)

正则表达式默认采用贪婪匹配模式。

  • 贪婪匹配:尽可能多的匹配字符
  • 惰性匹配:尽可能少的匹配字符

因为存在 *+?{n,}{n,m}等这类可以限定前一个匹配项次数的“量词”,且这些“量词”皆是虚指,如 * 表示零次或多次,+表示一次或多次。

而默认使用贪婪模式会尽可能多的匹配。如:

/a.*a/” => greedy can be dangerous at times

可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。

/a.*a/” => greedy can be dangerous at times

一览:贪婪模式加 “?” 转变为惰性模式

贪婪模式 解释 惰性模式 解释
? 重复0次或1次,取最大满足次数(最多1次)。 ?? 重复0次或1次,取最少满足次数(最少0次)。
+ 重复1次或多次,取最大满足次数(不限次数)。 +? 重复1次或多次,取最少满足次数(最少1次)。
* 重复任意次,取最大满足次数(不限次数)。 *? 重复任意次,取最少满足次数(最少0次)。
{n,m} 重复n到m此,取最大满足次数(最少m次)。 {n,m}? 重复n到m此,取最少满足次数(最少n次)。
{n,} 重复n次以上,取最大满足次数(不限次数)。 {n,}? 重复n次以上,取最少满足次数(最少n次)。

2、常见语法(表格)

2.1、元字符

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

元字符 描述 示例
. 句点匹配任意单个字符除了换行符。 1. f.o 匹配在字母“f”和“o”之间的任意一个字符;例如 fao、 f9o、 f#o 等
2. .. 匹配任意两个字符
3. .end 匹配在字符串 end 之前的任意一个字符
[ ] 字符种类。匹配方括号内的任意字符。 1. b[aeiu]t bat、 bet、 bit、 but
2. [ab][12] 一个包含2个字符的字符串,第一个字符是“a或“b”,
     然后是“1”或“2”,即可匹配项为 a1、a2、b1、b2
3. [0-9] 匹配0-9中任意一个数字
[^ ] 否定的字符种类。匹配除了方括号里的任意字符 1. [^aeiou] 一个非元音字符,即除了aeiou 之外的任意字符
2. [^\t\n] 不匹配制表符或者\n
* 匹配>=0个重复的在*号之前的字符。 1. b(an)* 匹配以b开头的an出现0次或多次的,如单词b,ban,banan
2. [A-Za-z0-9]* 全文匹配
+ 匹配>=1个重复的+号前的字符。 1. b(an)+ 匹配以b开头的an出现1次或多次的,如 ban, banan
? 标记?之前的字符为可选. 1. b(an)? 匹配以b开头的an出现1次或0次的,如 b,ban
{n,m} 匹配num个大括号之前的字符或字符集 (n <= num <= m). 1. a{3} 匹配3个连续的a组成的单词,即“aaa”
2. b{2,3} 匹配b连续出现2到3次的单词,即“bb”或“bbb”
3. c{2,} 匹配c连续出现2个以上的单词,即“c”,“cc”,“ccc”,“cccc”
4. 注意,没有c{,3}这样的语法
(xyz) 字符集,匹配与 xyz 完全相等的字符串. 1. (abc) 匹配abc
2. #(abc)? 匹配'#'后“abc”出现一次或0次,即“#abc”或“#”
| 或运算符,匹配符号前或后的字符. 1. foo|bar 匹配 foo 或 bar
\ 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ | 1. \(|\[|\{|\\\| 匹配“(”或“[”或“{”或“\”或“|”
^ 从开始行开始匹配. 1. ^(T|t)he 匹配以 The 或 the 开头的字符串。
2. ^(T|t)he.* 匹配以The 或 the 开头的整行
$ 从末端开始匹配. 1. end$ 匹配以end结尾的字符串
2.2、特殊符号
简写 描述
. 除换行符外的所有字符
\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 行终止符
\b 匹配任何单词边界( \B 与之相反)如\bThe\b
\b\A(\Z) 匹配字符串的起始(结束)( 另见上面介绍的^和$)注意区别:
^ 和 $ 分别代表一行(line)的开始和结束的位置;
\A 和 \Z 分别代表输入(input)的开始和结束位置
2.3、扩展表示法
格式 说明 示例
(?iLmsux) 在正则表达式中嵌入一个或者多个特殊“ 标记” 参数(或者通过函数/方法) ( ?x),(?im)
(?:…) 表示一个匹配不用保存的分组 (?:\w+\.)*
(?P…) 或 (?‘name’…) 或
(?…)
像一个仅由 name 标识而不是数字 ID 标识的正则分组匹配 (?P)
(?P=name) 匹配先前命名的捕获组匹配的相同文本。 (?P=data)
(?#…) 表示注释,所有内容都被忽略 (?#comment)
(?=…) 匹配条件是如果…出现在之后的位置,而不使用输入字符串;称作正向前视断言 (?=.com)
(?!…) 匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言 (?!.net)
(?<=…) 匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言 (?<=800-)
(? 匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言 (?
(?(id/name)Y|N ) 如果分组所提供的 id 或者 name(名称)存在,就返回正则表达式的条件匹配 Y
如果不存在,就返回 N; |N 是可选项
(?(1)y|x)
(?>…) 占用相应匹配内容,禁止随后的匹配项进行回溯匹配。非捕获组。
(?|…) 不允许为所有封闭的捕获组增加捕获组ID。

除此之外,还有递归、条件语句、内联、预定表达式等等…

扩展表示法,是以问号开始,形如(?…)。它们通常用于在判断匹配之前提供标记,实现一个前视(或者后视)匹配,或者条件检查。尽管圆括号使用这些符号,但是只有(?P)表述一个分组匹配。所有其他的都没有创建一个分组。

正则表达式模式 匹配的字符串
(?:\w+.)* 以句点作为结尾的字符串,例如“google.”、“twitter.”、“facebook.”,但是这些匹配不会保存下来供后续的使用和数据检索
(?#comment) 此处并不做匹配,只是作为注释
(?=.com) 如果一个字符串后面跟着“.com”才做匹配操作,并不使用任何目标字符串
(?!.net) 如果一个字符串后面不是跟着“.net”才做匹配操作
(?<=800-) 如果字符串之前为“800-”才做匹配,假定为电话号码,同样,并不使用任何输入字符串
(? 如果一个字符串之前不是“192.168.”才做匹配操作,假定用于过滤掉一组 C 类 IP 地址
(?(1)y|x) 如果一个匹配组 1(\1)存在, 就与 y 匹配; 否则,就与 x 匹配

2.4、子表达式

正则中用 ( ) 划分子表达式。目的是为了将其视为单一的实体来使用。

一般而言,在编程语言中分组id为0,表示匹配到的全部内容,分组id为1,表示匹配到的第一个子表达式的内容,以此类推。

使用 ..>可以自定义分组名字,便于我们通过标签名取分组。下列以python为例:
正则表达式(详解)_第5张图片

每一个子表达式视为一个分组,在正则内部可以通过 $1、$2 引用,或者 \1 、\2。

2.4.1 捕获分组

在正则中,我们也可以使用 $+序号 表示分组,$1 表示第一个分组, ${foo}表示捕获被命名为foo的分组的字符串内容。

  • 使用 $+序号 的方式一般用于 replace 替换时获取匹配项的分组内容。

以JavaScript为例:使用$1、$2 提取分组内容。需要注意的是,不存在 $0,如果想表示全部匹配项的话,使用 $& 表示。
正则表达式(详解)_第6张图片
示例:将匹配项替换为空字符串;将匹配项左右两侧加括号。
正则表达式(详解)_第7张图片
如果想在正则表达式之外使用这些,需要加上前缀 RegExp.$1 …
示例:
正则表达式(详解)_第8张图片

其他的,$` 表示捕获匹配项左侧文本内容,$' 表示捕获匹配项右侧文本内容。
在这里插入图片描述
不捕获分组

此外,如果分组标明为 (?:..) 则表示不捕获该分组。
示例:子表达式1不捕获后,分组1代指子表达式2捕获的内容。但是整体匹配项($&)不受影响。
正则表达式(详解)_第9张图片

一览:

符号 说明
$$ 一个$符号
$1,$2… 第1/2个分组捕获的匹配项
$& 全部匹配项($1+$2…$n)
&` 匹配项前面的内容
&’ 匹配项后面的内容
2.4.2 反向引用(匹配叠词)

反向引用也基于分组的概念。规则为:由外向内,由左向右

形式为:\1\2、… 分别表示引用第一个子表达式、第二子表达式…

与 $1 方式捕获不同的是,\1 方式捕获可用于正则模式串中。

匹配叠词
示例:可以用这种方式匹配叠词。
正则表达式(详解)_第10张图片
分析:
对于字符串“abcdeefghhhd”而言,如果我们想匹配叠词,我们应该怎么操作呢?

\w{2,} 不行,它只匹配到了两个字符。

而我们想要的是之前匹配到的字符再出现一次,因此我们自然想到子表达式。只需要再复用一次上一次子表达式匹配到的项即可。
正则表达式(详解)_第11张图片
此表达式,利用 \1 将第一个分组的匹配项引用到模式串中。

匹配过程如下:

  • 对于“abcdeefghhhd”而言,第一个 (\d) 匹配到 a 时,\1 引用 a。 此时模式串等价于 aa 。很显然下一个字符是b,不匹配。
  • 同理,继续向后匹配“abcdeefghhhd”, 模式串 bb 。不匹配
  • 直到“abcdeefghhhd” 匹配到 e 时,模式串为 ee ,下一个字符也是 e ,匹配成功。

引用顺序
由外向内,自左向右。

下面使用python举例:
正则表达式(详解)_第12张图片
由外向内:

  • 第一组是a所在的括号,匹配到 “abcd”
  • 第二组是b所在的括号,匹配到 “bcd”
    自左向右:
  • 第三组是c所在的括号,匹配到 “c”
  • 第四组是d所在的括号,匹配到 “d”

回溯:内层括号匹配完之后,向上回溯。然后从第五组,e所在的括号开始。

正则表达式(详解)_第13张图片

3、正则工具

3.0、正则教程

正则教程:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md
github 40k start的正则教程。
正则表达式(详解)_第14张图片

3.1、正则大全

正则大全:https://any86.github.io/any-rule/
该网站收录了很多特殊正则表达式,拿来即用。正则表达式(详解)_第15张图片

3.2、正则解析

正则解析:https://jex.im/regulex
该网站可以分析正则表达式,以图解的形式拆分解析,便于理解。正则表达式(详解)_第16张图片

3.3、正则练习

正则练习:https://regexone.com/
该网站可以进行一些简单的正则练习,以刷题闯关的方式学习正则表达式。正则表达式(详解)_第17张图片

3.4、正则工具

正则工具:https://regex101.com/
该网站提供在线正则匹配,同时支持语法提示和代码生成,功能非常强大。正则表达式(详解)_第18张图片

你可能感兴趣的:(#,正则表达式,正则表达式,前端,后端)