正则表达式基本知识

Author:onceday date:2022年8月25日

长路漫漫,路上很美…

本文收集整理于互联网,可参考以下文档:

  • 正则表达式 教程 W3Cschool
  • 正则表达式 教程 菜鸟教程
  • 正则表达式在线工具 菜鸟教程

1.引言

正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

正则表达式的"祖先"可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为"神经网事件的表示法"的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为"正则集的代数"的表达式,因此采用"正则表达式"这个术语。

随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。

正则表达式的优势在于其抽象匹配能力,无需通过多余的编程,即可按照固定的规则做出复杂的匹配效果,在效率要求不高的场景使用性非常高。

但缺陷也同样源自于此,在过于复杂的匹配时,性能会极大降低,因此需要综合场景来使用。

下面是一个实际的例子,只允许用户名包含字符、数字、下划线和连接字符 -,并限制用户名的长度:

^[a-z0-9_-]{3,15}$
  • ^,匹配输入字符串的开始位置。
  • [a-z0-9_-]匹配单个数字、字母、连接符。
  • {3,15}表示3-15个字符的长度。

在不同的语言中都有正则表达式的支持,都会有一些自由的特殊性质。

下面主要介绍一些通用的规则。

2.语法

正则表达式主要由普通字符和特殊字符组成。

2.1 普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

非打印字符包括以下部分:

字符描述
\cx匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。
\f匹配一个换页符。等价于 \x0c\cL
\n匹配一个换行符。等价于 \x0a \cJ
\r匹配一个回车符。等价于 \x0d \cM
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\t匹配一个制表符。等价于 \x09\cI
\v匹配一个垂直制表符。等价于\x0b\cK
2.2 特殊字符

所谓特殊字符,就是一些有特殊含义的字符,如上面说的*.txt中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个\

许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符 () 放在它们前面。

特殊字符描述
$匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 \n \r。要匹配 $ 字符本身,请使用 \$
()标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( \)
*匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*
+匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+
.匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \.
[]标记一个中括号表达式的开始和结束。要匹配 [],请使用 \[\]
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配?字符,请使用 \?
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, n 匹配字符 n\n 匹配换行符。序列 \\ 匹配 \,而 \( 则匹配 (
^匹配输入字符串的开始位置;在方括号表达式中使用时表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^
{}标记限定符表达式的开始和结束。要匹配 {或者},请使用 \{\}
``
2.3 限定字符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。

限定符描述
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 z 以及 zoo* 等价于{0,}
+匹配前面的子表达式一次或多次。例如,zo+ 能匹配 zo 以及 zoo,但不能匹配 z。+ 等价于 {1,}
?匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 dodoes 中的 doesdoxy 中的 do? 等价于 {0,1}
{n}n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 Bob 中的 o,但是能匹配 food 中的两个o
{n,}n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 Bob 中的 o,但能匹配 foooood"中的所有 oo{1,} 等价于 o+o{0,} 则等价于 o*
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 fooooood 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。

实例:正则表达式匹配编号为任何位数的章节标题,/Chapter [1-9][0-9]*/

2.4 定位符

定位符能够将正则表达式固定到行首或行尾。还可以限制正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

字符描述
^匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与\n\r 之后的位置匹配。
$匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n\r 之前的位置匹配。
\b匹配一个字边界,即字与空格间的位置。
\B非字边界匹配。

注意:不能将限定符与定位点一起使用。由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。

匹配一个章节标题,该标题只包含两个尾随数字,并且出现在行首:

/^Chapter [1-9][0-9]{0,1}/

真正的章节标题不仅出现行的开始处,而且它还是该行中仅有的文本。它即出现在行首又出现在同一行的结尾。下面的表达式能确保指定的匹配只匹配章节而不匹配交叉引用。通过创建只匹配一行文本的开始和结尾的正则表达式,就可做到这一点。

/^Chapter [1-9][0-9]{0,1}$/

下面的表达式匹配单词 Chapter 的开头三个字符,因为这三个字符出现字边界后面:

/\bCha/

以下是\b\B的区别:

/\bapt/   可以匹配apititude但不能匹配chapter
/\Bapt/   可以匹配chapter但不能匹配apititude
2.5 选择字符

用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。

选择字符描述
(pattern)匹配 pattern 并获取这一匹配。
(?:pattern)匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
(?=pattern)正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。
(?!pattern)负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。
2.6 其他额外元字符
字符描述
\d匹配一个数字字符。等价于 [0-9]。
\D匹配一个非数字字符。等价于 [^0-9]
\w匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W匹配任何非单词字符。等价于 [^A-Za-z0-9_]
\xn匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,\x41 匹配 A\x041 则等价于 \x04 & 1。正则表达式中可以使用 ASCII 编码。
\num匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,(.)\1 匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号
2.7 运算符优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。

相同优先级的从左到右进行运算,不同优先级的运算先高后低。下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

运算符优先级描述
\1转义符
(), (?😃, (?=), []2圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}3限定符
^, $, \任何元字符、任何字符4定位点和序列(即:位置和顺序)
``5

3.综合实例

var str = "https://www.runoob:80/html/html-tutorial.html";
var patt1 = /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
arr = str.match(patt1);

第三行代码str.match(patt1)返回一个数组,实例中的数组包含 5 个元素,索引 0 对应的是整个字符串,索引 1 对应第一个匹配符(括号内),以此类推。

第一个括号子表达式捕获 Web 地址的协议部分。该子表达式匹配在冒号和两个正斜杠前面的任何单词。

第二个括号子表达式捕获地址的域地址部分。子表达式匹配非:/之后的一个或多个字符。

第三个括号子表达式捕获端口号(如果指定了的话)。该子表达式匹配冒号后面的零个或多个数字。只能重复一次该子表达式。

最后,第四个括号子表达式捕获 Web 地址指定的路径和 / 或页信息。该子表达式能匹配不包括#或空格字符的任何字符序列。

将正则表达式应用到上面的 URI,各子匹配项包含下面的内容:

  • 第一个括号子表达式包含 https
  • 第二个括号子表达式包含 www.runoob
  • 第三个括号子表达式包含 :80
  • 第四个括号子表达式包含 /html/html-tutorial.html

4.额外参考文档

正则表达式是一个典型的工具,虽则提供方的不同,其规则也有细微的区别,所以本文档目的在于方便查阅。

像这类工具语言,最好的学习方式就是实践,因此,搭配上面的规则,以及下面的文档,逐渐深入学习。

匹配规则:

  • 匹配规则-菜鸟教程
  • 匹配规则-W3Cschool

示例:

  • W3Cschool
  • 菜鸟教程

更多推荐

正则表达式基本知识