1 简介
正则表达式允许您定义一个模式并通过该模式对字符串执行相应的操作。 与模式匹配的子字符串称为“匹配”。
正则表达式是定义搜索模式的字符串。
正则表达式主要用于以下场景:
正则表达式不适合在这些场景中使用:
实现正则匹配的引擎有很多,各有各的特点。 本书将避免讨论(引擎之间的)功能差异,而是仅讨论大多数情况下不同引擎所共有的功能。
整本书都使用了示例。 因此,本书可能稍微偏向正则表达式引擎。
2 基础知识
正则表达式通常采用 // 格式,为了简洁起见,通常省略结尾的 /。 我们将在下一章详细讨论标志。
让我们从正则表达式 /p/g 开始。 现在,将 /g 标志视为静态。
我们可以看到,/p/g 匹配所有小写 p 字符。
注意
默认情况下,正则表达式区分大小写。
在输入字符串中找到的正则表达式模式的实例称为“匹配”。
3个字符组
可以匹配一组字符中的一个字符。
[aeiou]/g 匹配输入字符串中的所有元音。
这是另一个例子:
我们匹配 ap,后跟元音,然后是 t。
有一个更直观的快捷方式可以匹配连续范围内的字符。
警告
表达式 /[az]/g 仅匹配一个字符。 在上面的示例中,每个字符都有一个单独的匹配。 不是整个字符串匹配。
我们还可以在正则表达式中组合范围和单个字符。
我们的正则表达式 /[A-Za-z0-9_-]/g 匹配一个字符,该字符必须(至少)是以下字符之一:
我们也可以“否定”这些规则:
/[aeiou]/g 和 /[^aeiou]/g 之间的唯一区别是 ^ 紧跟在左括号后面。 其目的是“否定”括号中定义的规则。 它的意思是:
匹配除 a、e、i、o 或 u 之外的任何字符
3.1 示例
非法用户名字符
指定字符
/[A-HJ-NP-Za-kmnp-z2-9]/g
4个字符转义
字符转义是某些常见字符类的简写表达式。
4.1 数字字符\d
转义字符\d表示匹配数字字符0-9。 相当于[0-9]。
\D与\d相反,相当于[^0-9]。
4.2 单词字符\w
转义字符 \w 匹配单词字符。 包括:
相当于[a-zA-Z0-9_]
4.3 空白字符\s
转义字符 \s 匹配空白字符。 匹配的确切字符集取决于正则表达式引擎,但大多数至少包括:
其他可能包括垂直制表符 (\v)。 自识别引擎通常匹配分隔符类别中的所有字符。 然而,技术细节通常并不重要。
4.4 任意字符。
但这不是典型的角色逃脱。 。 可以匹配任意1个字符。 (除了换行符\n之外,还可以通过修饰符来匹配换行符\n)
5 逃脱
在正则表达式中,一些字符具有特殊含义,我们将在本章中探讨:
当我们想要按字面匹配这些字符时,我们可以通过在这些字符前面添加\来“转义”它们。
5.1 示例
内嵌评论
星号包围的子字符串
第一个和最后一个星号是字面意思,因此必须用 \* 转义。 字符集中的星号不需要转义,但为了清楚起见我将其转义。 紧跟在字符集后面的星号表示字符集重复,我们将在后面的章节中对此进行探讨。
6组
顾名思义,组用于“组合”正则表达式的组成部分。 这些组可用于:
在本章中我们首先学习群体是如何工作的,后续章节中将会有更多的例子。
6.1 捕获组
捕获组由 (…) 表示。 这是一个说明性示例:
捕获组允许提取部分匹配项。
通过该语言的常规函数,您将能够提取括号之间的匹配文本。
捕获组还可用于对正则表达式的各个部分进行分组,以便于重复。 虽然我们将在接下来的章节中详细介绍重复,但这里有一个示例演示了组的有用性。
其他时候,它们用于对正则表达式的逻辑上相似的部分进行分组以提高可读性。
6.2 回溯
回溯允许引用先前捕获的子字符串。
您可以使用 \1 匹配第一组,\2 匹配第二组,依此类推...
您不能使用回溯来减少正则表达式中的重复。 它们指的是组的匹配,而不是模式的匹配。
以下是演示常见用例的示例:
这无法通过重复的字符类来实现。
6.3 非捕获群
非捕获组与捕获组非常相似,只是它们不创建“捕获”。 相反,它采用 (?: ...) 的形式
非捕获组通常与捕获组一起使用。 也许您正在尝试使用捕获组来提取匹配的某些部分。 并且您可能希望在不影响捕获顺序的情况下使用组,在这种情况下,您应该使用非捕获组。
6.4 示例
查询字符串参数
我们单独匹配第一组键值对,因为这允许我们使用 & 分隔符作为重复组的一部分。
(基本)HTML 标签
根据经验,不要使用正则表达式来匹配 XML/HTML。 不过,我还是提供一个相关的例子:
姓名
查找:\b(\w+) (\w+)\b
替换:2, 1
在替换操作中,经常使用1、2; 在捕获中,使用\1、\2
更换前
John Doe
Jane Doe
Sven Svensson
Janez Novak
Janez Kranjski
Tim Joe
更换后
Doe, John
Doe, Jane
Svensson, Sven
Novak, Janez
Kranjski, Janez
Joe, Tim
回溯和复数
搜索:\bword(s?)\b
更换:1 美元
更换前
This is a paragraph with some words.
Some instances of the word "word" are in their plural form: "words".
Yet, some are in their singular form: "word".
更换后
This is a paragraph with some phrases.
Some instances of the phrase "phrase" are in their plural form: "phrases".
Yet, some are in their singular form: "phrase".
7 重复
重复是正则表达式的一个强大且常见的功能。 有多种方法可以在正则表达式中表达重复。
7.1 选项
我们可以用什么? 将某个部分设为可选(0 次或 1 次)。
另一个例子:
我们还可以通过编程使捕获组和非捕获组成为可选的。
7.2 零次或多次
如果我们想匹配零个或多个标记,我们可以使用 * 作为后缀。
我们的正则表达式甚至匹配空字符串。
7.3 一次或多次
如果我们想要匹配 1 个或多个标记,我们可以使用 + 作为后缀。
7.4 正好 x 次
如果我们想精确匹配特定标记 x 次,我们可以添加 {x} 后缀。 这在功能上相当于将标签复制粘贴 x 次。
下面是匹配大写六个字符的十六进制颜色代码的示例。
这里,标记{6}适用于字符集[0-9A-F]。
7.5 最小度数和最大度数之间
如果我们想匹配最小和最大次数之间的特定标签,我们可以在标签后面添加 {min,max} 。
警告
{min,max} 中的逗号后面不应有空格。
7.6 至少 x 次
如果我们想匹配某个特定标签至少 x 次,我们可以在标签后面添加 {x,}。 与 {min, max} 类似,但没有上限。
7.7 贪心模式注意事项
正则表达式默认使用贪婪模式。 在贪婪模式下,将匹配尽可能多的匹配字符。
添加 ? **重复运算符 (?, *, +, ...)** 之后,这可以使匹配“惰性”。
这里,也可以用[^"]来代替。(这是最佳实践)。
懒惰就是满足条件就停下来; 贪婪意味着只有当条件不再满足时才停止。
- 儿子
7.8 示例
比特币地址
视频
我们可以使用锚点来调整表达式,使其与最后一个不正确的链接不匹配,我们稍后会介绍这一点。
8 替补
交替允许匹配多个短语之一。 这比仅限于单个角色的角色组更强大。
使用管道符号 | 分隔多个短语
匹配 foo、bar 和 baz 之一。
如果只需要“交替”正则表达式的一部分,则可以使用组来包装它,可以是捕获组,也可以是非捕获组。
Try 后跟 foo、bar 和 baz 之一。
匹配 100-250 之间的数字:
这可以使用正则表达式范围工具生成。
例子
十六进制颜色
让我们改进之前的十六进制颜色匹配示例。
将 [0-9A-F]{6} 放在 [0-9A-F]{3} 前面非常重要。 否则:
暗示
正则表达式引擎从左到右交替尝试。
罗马数字
9 个修饰符
修饰符允许我们将正则表达式分成不同的“模式”。
修饰符是//后面的部分。
不同的引擎支持不同的修饰符。 这里我们只讨论最常见的修饰符。
9.1 全局修饰符(g)
到目前为止,所有示例都设置了全局修饰符。 如果未启用全局修饰符,正则表达式将不会匹配第一个字符之后的任何其他字符。
9.2 不区分大小写的修饰符 (i)
顾名思义,启用此修饰符将使常规匹配不区分大小写。
9.3 多行模式修饰符(m)有限支持
在 Ruby 中,m 修饰符执行其他函数。
多行修饰符涉及处理包含换行符的“多行”字符串时锚点的处理。 默认情况下,/^foo$/ 仅匹配“foo”。
我们可能希望它甚至在多行字符串中的一行上匹配 foo 。
我们以“bar\nfoo\nbaz”为例:
bar
foo
baz
如果没有 m 修饰符,上面的字符串将被视为单行 bar\nfoo\nbaz,并且正则表达式 ^foo$ 无法匹配任何字符。
如果存在 m 修饰符,则以上字符串将被视为 3 行。 ^foo$ 匹配中间线。
9.4 点全修饰符 有限支持
以前不支持此修饰符。 Ruby也不支持这种修饰,但用m表示。
.通常匹配除换行符之外的任何字符。 使用dot all修饰符后,还可以匹配换行符。
10 个锚点
锚本身不匹配任何东西。 然而,它们限制了比赛发生的地点。
您可以将锚点视为“隐形字符”。
10.1 行首^
在正则表达式的开头插入 ^ 符号,以便正则表达式的其余部分必须从字符串的开头匹配。 您可以将其视为始终匹配字符串开头的不可见字符。
10.2 行尾
在正则表达式的末尾插入 $ 符号,类似于行的开头。 您可以将其视为始终匹配字符串末尾的不可见字符。
^ 和 $ 锚点通常一起使用,以确保整个正则表达式字符串匹配,而不仅仅是其中的一部分。
让我们回到 中的示例,并在正则表达式的末尾添加两个锚点。
没有这两个锚点,http/2 和 shttp 也会被匹配。
10.3 字边界\b
单词边界是字符和非单词字符之间的位置。
单词边界锚 \b,存在于匹配字符和非单词字符之间的虚构的不可见字符。
暗示
字符包括 az、AZ、0-9 和 _。
还有一个非单词边界锚 \B。
顾名思义,它匹配除单词边界之外的所有内容。
暗示
^…$ 和 \b…\b 是常见模式,您几乎总是需要这两个模式来防止意外匹配。
10.4 示例
尾随空格
标题
无锚:
11 零宽度断言()
零宽度断言可用于验证条件而不匹配任何文本。
只能看,不能动。
前瞻断言() 11.1 前瞻断言()
向前()
请注意以下字符如何不匹配。 这可以通过正面观察来确认。
常规引擎使用 (?=[aeiou]) 和 (?=\1) 进行检查。
消极的()
如果没有锚点,每个示例中没有 # 的部分将被匹配。
否定先行断言通常用于防止某些短语的匹配。
11.2 示例
密码验证
/^(?=.*\d)(?=.*[az])(?=.*[AZ])(?=.*[a-zA-Z]).{8,}$/
零宽度断言可用于验证多个条件。
带引号的字符串
如果没有前瞻断言,我们最多能做的是:
12 个高级示例
评论
[\s\S] 是一种匹配任何字符(包括换行符)的技术。 我们避免使用 dot-all 修饰符,因为我们需要使用 . 代表单行注释。
24小时
IP地址
元标签
代替:
浮点数
前向断言 (?=\.\d|\d) 确保不匹配。
HSL颜色
0 到 360 之间的整数
百分比
HSL 和百分比
13 下一步
如果您想了解有关正则表达式及其工作原理的更多信息:
感谢您的阅读!本教程确实帮助我学习了正则表达式