正则表达式
正则表达式
一、概述
正则表达式(Regular Expression)是一种用于匹配文本的模式,广泛应用于文本搜索、替换、数据验证等领域。它通过定义规则来描述字符串的格式和内容,可以匹配复杂的文本结构。
二、匹配单个字符
在正则表达式中,匹配单个字符是构建复杂模式的基础。主要包括普通字符和特殊字符(如点号
.)。以下是对这两种匹配单个字符方式的详细说明:
1. 普通字符
定义:普通字符是指除正则表达式元字符(如
., *, +, ?,
^, $, [], (),
{}, |, \
等)之外的所有字符。它们在正则表达式中代表自身,直接用于匹配文本中的相应字符。
用法: - 直接匹配:普通字符直接在正则表达式中出现,表示要匹配该字符本身。
示例: - 匹配单个字符: -
正则表达式:a - 匹配字符串:"apple" 中的第一个 "a"
- 匹配多个普通字符:
- 正则表达式:
cat - 匹配字符串:"The cat sat on the mat." 中的 "cat"
- 正则表达式:
- 匹配带有特殊意义的字符:
- 如果需要匹配元字符本身,如
.、*,必须使用转义字符\。 - 例如,匹配句点
.:- 正则表达式:
\. - 匹配字符串:"End of sentence." 中的句点。
- 正则表达式:
- 如果需要匹配元字符本身,如
注意事项: -
区分大小写:默认情况下,正则表达式是区分大小写的。例如,a
不匹配 A。可以使用标志(如 i)来忽略大小写。 -
转义字符:当普通字符与元字符冲突时,需要使用反斜杠
\ 进行转义。例如,要匹配字符 *,应使用
\*。
示例代码:
1 | import re |
2. 点号(.)
定义:点号 .
是一个特殊的正则表达式元字符,用于匹配除换行符(\n)之外的任意单个字符。
用法:
- 通配符:在正则表达式中使用
.可以匹配任何字符(除换行符),常用于模糊匹配。
示例: - 基本用法: -
正则表达式:a.b - 匹配字符串:"aab", "acb", "a3b" 等,匹配
"a" 后跟任意一个字符,再跟 "b"
- 多重通配:
- 正则表达式:
... - 匹配任何三个连续的字符,如 "abc", "123", "a b"
- 正则表达式:
- 与重复符结合:
- 正则表达式:
a.*b - 匹配以 "a" 开头,以 "b" 结尾,中间可以有任意数量的任意字符,如 "ab", "a123b", "a!@#b"
- 正则表达式:
高级用法:
匹配换行符:
- 默认情况下,
.不匹配换行符。如果需要匹配包括换行符在内的任意字符,可以使用 单行模式(re.DOTALL或s标志)。
示例:
1
2
3
4
5
6
7
8
9
10
11
12import re
# 默认情况下,'.' 不匹配换行符
pattern = r'a.b'
text = 'a\nb'
match = re.search(pattern, text)
print(match) # 输出: None
# 使用 re.DOTALL 使 '.' 匹配换行符
match = re.search(pattern, text, re.DOTALL)
if match:
print(match.group()) # 输出: a\nb- 默认情况下,
非贪婪匹配:
- 与重复符(如
*、+)结合使用时,.可以进行非贪婪匹配,尽可能少地匹配字符。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13import re
text = '<div>Content</div><div>More Content</div>'
# 贪婪匹配
pattern = r'<div>.*</div>'
match = re.search(pattern, text)
print(match.group()) # 输出: <div>Content</div><div>More Content</div>
# 非贪婪匹配
pattern = r'<div>.*?</div>'
match = re.search(pattern, text)
print(match.group()) # 输出: <div>Content</div>- 与重复符(如
常见误区:
- 误认为
.匹配换行符:- 很多人初学时误以为
.可以匹配所有字符,包括换行符。实际上,需要使用单行模式或特定的标志来实现这一点。
- 很多人初学时误以为
- 过度依赖
.进行匹配:- 虽然
.是强大的通配符,但在某些情况下,过度使用可能导致匹配过于宽泛,难以控制。应根据具体需求合理使用。
- 虽然
最佳实践:
明确需求:在使用
.时,确保明确知道它匹配的范围,必要时使用限定符或其他元字符进行精确控制。结合其他元字符:
.通常与其他元字符(如*,+,?,[],()等)结合使用,以构建更复杂和精确的匹配模式。使用模式标志:根据需要调整正则表达式的行为,如使用
re.DOTALL让.匹配换行符,或使用re.IGNORECASE进行不区分大小写的匹配。
更多示例:
匹配电子邮件地址中的任意字符:
1
2
3
4
5
6import re
pattern = r'\w+@\w+\.\w+'
text = 'Contact us at support@example.com'
match = re.search(pattern, text)
print(match.group()) # 输出: support@example.com匹配包含特殊字符的文件名:
1
2
3
4
5
6import re
pattern = r'file\.\w+'
text = 'The file.txt is ready.'
match = re.search(pattern, text)
print(match.group()) # 输出: file.txt使用
.进行复杂匹配:1
2
3
4
5
6
7import re
# 匹配以 "start" 开头,以 "end" 结尾,中间有任意字符
pattern = r'^start.*end$'
text = 'start123end'
match = re.match(pattern, text)
print(match.group()) # 输出: start123end
三、匹配一组字符
- 字符集:
- 定义:字符集使用方括号
[]包含一组字符,表示可以匹配方括号内的任意一个字符。 - 匹配逻辑:正则表达式引擎会尝试匹配字符串中的单个字符,只要这个字符出现在字符集中即可。
- 示例:
- 正则表达式
[abc]:- 匹配字符串中的 "a"、"b" 或 "c" 中的任意一个字符。
- 如输入 "apple":
[abc]会匹配 "a"。 - 如输入 "bake":
[abc]会匹配 "b"。 - 如输入 "cat":
[abc]会匹配 "c"。
- 正则表达式
- 组合使用:
[aeiou]:匹配任意一个元音字母("a"、"e"、"i"、"o"、"u")。[0123456789]:匹配任意一个数字字符。
- 字符集内的特殊符号:
- 如果字符集内包含元字符如
.、*、+等,它们在字符集中失去特殊意义,仅作为普通字符处理。如:[.*+]匹配的是 "."、"*"、"+" 三个字符中的任意一个。
- 如果字符集内包含元字符如
- 定义:字符集使用方括号
- 范围:
- 定义:字符集内的字符可以使用连字符
-来表示一个范围,这样可以简化书写。 - 示例:
[a-z]:匹配所有小写字母,从 "a" 到 "z"。- 如输入 "dog":正则
[a-z]可以匹配 "d"、"o"、"g" 中的任何一个。 [a-zA-Z]:匹配所有字母,不区分大小写。
- 如输入 "dog":正则
[0-9]:匹配所有数字,从 "0" 到 "9"。- 如输入 "2024":正则
[0-9]可以匹配 "2"、"0"、"2"、"4" 中的任何一个。
- 如输入 "2024":正则
- 多个范围组合:
[a-z0-9]:匹配小写字母和数字,即小写字母或数字中的任意一个。[A-Fa-f0-9]:匹配十六进制数字中的任意一个字符,包括 "A-F"、"a-f"、"0-9"。
- 范围的注意事项:
- 范围中的起始字符和结束字符必须按照 ASCII 码的顺序,否则可能产生错误的结果。
- 例如,
[z-a]是无效的,因为 "z" 的 ASCII 码大于 "a"。
- 定义:字符集内的字符可以使用连字符
- 否定字符集:
- 定义:使用
^在字符集的开头表示否定字符集,即匹配不在字符集内的任何字符。 - 示例:
[^abc]:匹配除了 "a"、"b"、"c" 之外的任意字符。- 如输入 "dog":
[^abc]匹配 "d"、"o"、"g"。
- 如输入 "dog":
[^0-9]:匹配非数字的字符。- 如输入 "Hello123":
[^0-9]匹配 "H"、"e"、"l"、"l"、"o"。
- 如输入 "Hello123":
- 定义:使用
- 字符集
[ ]是匹配任意一个包含的字符。- 范围
[a-z]可以表示连续字符的范围,简化字符集定义。- 否定字符集
[^ ]用于匹配不在指定字符集中的字符。
四、使用元字符
元字符是具有特殊意义的字符,能够帮助我们构建更强大的正则表达式。以下是常见的元字符及其功能:
\d(匹配数字):- 定义:
\d匹配任意的数字字符。这个元字符等价于字符集[0-9],也就是说它可以匹配任意一个从 "0" 到 "9" 的数字。 - 示例:
- 正则表达式
\d可以匹配字符串中的任何一个数字。 - 如输入 "Price: 45 dollars":
\d匹配 "4" 和 "5"。\d\d可以匹配 "45"(连续的两个数字)。
- 正则
\d{3}匹配三位数字的组合,如 "123" 或 "456"。
- 正则表达式
- 定义:
\w(匹配字母、数字或下划线):- 定义:
\w匹配任何字母(大写或小写)、数字或下划线_。它等价于字符集[A-Za-z0-9_]。 - 示例:
- 正则表达式
\w可以匹配任何一个字母、数字或下划线。 - 如输入 "user_name123":
\w匹配 "u"、"s"、"e"、"r"、"_"、"n"、"a"、"m"、"e"、"1"、"2"、"3"。\w+可以匹配整个字符串 "user_name123"。
- 正则
\w{5}可以匹配连续五个字母、数字或下划线的组合,如 "abc12" 或 "user_1"。
- 正则表达式
- 定义:
\s(匹配空白字符):- 定义:
\s匹配任何空白字符,包括空格、制表符(Tab)、换行符(\n)和回车符(\r)。这对于处理带有空格或其他空白字符的文本时非常有用。 - 示例:
- 正则表达式
\s可以匹配字符串中的任意一个空白字符。 - 如输入 "Hello World":
\s匹配两个单词之间的空格。
- 如输入 "Line1":
\s可以匹配换行符。
- 正则
\s+可以匹配一个或多个连续的空白字符,适合用来处理多个空格的情况。
- 正则表达式
- 定义:
\D(匹配非数字):- 定义:
\D是\d的反义,匹配任何非数字字符。 - 示例:
- 正则表达式
\D可以匹配字符串中除了数字以外的任意字符。 - 如输入 "Room 101":
\D匹配 "R"、"o"、"o"、"m"、" "(空格)。
\D+匹配连续的非数字字符,如 "Room "。
- 正则表达式
- 定义:
\W(匹配非字母、数字或下划线):- 定义:
\W是\w的反义,匹配任何非字母、非数字或非下划线的字符。 - 示例:
- 正则表达式
\W可以匹配除了字母、数字和下划线外的任意字符,如标点符号、空格等。 - 如输入 "Hello, World!":
\W匹配逗号 ","、空格 " " 和感叹号 "!"。
\W+匹配一个或多个连续的非字母、非数字或非下划线的字符,如匹配 ", World!"。
- 正则表达式
- 定义:
\S(匹配非空白字符):- 定义:
\S是\s的反义,匹配任何非空白字符。 - 示例:
- 正则表达式
\S可以匹配除了空格、制表符、换行符外的任意字符。 - 如输入 "Hello World":
\S匹配 "H"、"e"、"l"、"l"、"o"、"W"、"o"、"r"、"l"、"d"。\S+可以匹配 "Hello" 和 "World" 两个单词。
- 正则表达式
- 定义:
\d:匹配任何数字字符,等价于[0-9]。\w:匹配字母、数字或下划线,等价于[A-Za-z0-9_]。\s:匹配任何空白字符,包括空格、制表符、换行符等。\D、\W、\S:分别匹配非数字、非字母/数字/下划线、非空白字符。
五、重复匹配
重复匹配操作符用于指定前一个字符或子表达式出现的次数,从而构建灵活的正则表达式。这些操作符能够匹配多次重复的字符序列。以下是常见的重复匹配操作符及其使用方法:
*(匹配前一个字符0次或多次):- 定义:
*表示匹配前一个字符0次或多次,即前一个字符可以不出现,也可以出现多次。 - 示例:
- 正则表达式
a*:- 匹配空字符串(因为 "a" 可以出现0次)以及任何包含多个 "a" 的字符串。
- 如输入 "":
a*匹配空字符串。 - 如输入 "aa":
a*匹配整个字符串 "aa"。 - 如输入 "baaa":
a*匹配 "aaa" 部分。
.*(点号.匹配任意字符,*匹配0次或多次):- 匹配任意长度的字符串,包括空字符串。
- 如输入 "hello world":
.*匹配整个字符串。
- 正则表达式
- 定义:
+(匹配前一个字符1次或多次):- 定义:
+表示匹配前一个字符1次或多次,即前一个字符至少出现一次。 - 示例:
- 正则表达式
a+:- 匹配一个或多个连续的 "a" 字符。
- 如输入 "a":
a+匹配 "a"。 - 如输入 "aaa":
a+匹配 "aaa"。 - 如输入 "baaa":
a+匹配 "aaa" 部分。
\d+(\d匹配数字,+匹配1次或多次):- 匹配一个或多个连续的数字。
- 如输入 "123abc456":
\d+分别匹配 "123" 和 "456"。
- 正则表达式
- 定义:
?(匹配前一个字符0次或1次):- 定义:
?表示匹配前一个字符0次或1次,即前一个字符可以出现一次或不出现。 - 示例:
- 正则表达式
a?:- 匹配0个或1个 "a" 字符。
- 如输入 "":
a?匹配空字符串。 - 如输入 "a":
a?匹配 "a"。 - 如输入 "ab":
a?匹配 "a" 部分。
- 正则表达式
colou?r:u?匹配 "u" 0次或1次,能够匹配 "color" 或 "colour"。- 如输入 "color":
colou?r匹配整个字符串。 - 如输入 "colour":
colou?r也匹配整个字符串。
- 正则表达式
- 定义:
{n}(匹配前一个字符恰好n次):- 定义:
{n}表示匹配前一个字符恰好 n 次,即前一个字符必须精确地出现 n 次。 - 示例:
- 正则表达式
a{3}:- 匹配连续出现的三个 "a" 字符。
- 如输入 "aaa":
a{3}匹配整个字符串 "aaa"。 - 如输入 "aaaaa":
a{3}匹配前三个 "a"。
- 正则表达式
\d{4}:- 匹配恰好四位的数字。
- 如输入 "2024年":
\d{4}匹配 "2024"。
- 正则表达式
- 定义:
{n,m}(匹配前一个字符n到m次):- 定义:
{n,m}表示匹配前一个字符至少 n 次,至多 m 次。n 和 m 必须是非负整数。 - 示例:
- 正则表达式
a{2,4}:- 匹配两个到四个连续的 "a" 字符。
- 如输入 "aa":
a{2,4}匹配 "aa"。 - 如输入 "aaa":
a{2,4}匹配 "aaa"。 - 如输入 "aaaa":
a{2,4}匹配 "aaaa"。 - 如输入 "aaaaa":
a{2,4}匹配前四个 "a"。
- 正则表达式
\d{2,5}:- 匹配至少两位、至多五位的数字。
- 如输入 "12345":
\d{2,5}匹配 "12345"。 - 如输入 "123456":
\d{2,5}匹配前五个数字 "12345"。
- 正则表达式
- 定义:
*:匹配前一个字符0次或多次,适合匹配任意数量的字符,包括空字符。+:匹配前一个字符1次或多次,要求至少匹配一个字符。?:匹配前一个字符0次或1次,通常用于匹配可选字符。{n}:匹配前一个字符恰好 n 次,适用于精确匹配字符出现的次数。{n,m}:匹配前一个字符至少 n 次,至多 m 次,提供了灵活的次数范围匹配。
六、位置匹配
位置匹配是一种特殊的匹配方式,它并不匹配具体的字符,而是匹配字符在字符串中的位置。这些位置匹配符号可以用于构建对字符串特定部分的精确匹配条件。以下是常用的几种位置匹配符号及其详细说明:
^(匹配字符串的起始位置):- 定义:
^表示匹配字符串的起始位置,通常用于确保字符串以特定字符或子字符串开头。 - 示例:
- 正则表达式
^a:- 匹配任何以 "a" 开头的字符串。
- 如输入 "apple":
^a匹配 "a"(因为 "apple" 以 "a" 开头)。 - 如输入 "banana":
^a不匹配任何内容(因为 "banana" 不是以 "a" 开头)。
- 正则表达式
^Hello:- 匹配以 "Hello" 开头的字符串。
- 如输入 "Hello, world!":
^Hello匹配 "Hello"。 - 如输入 "Hi, Hello":
^Hello不匹配任何内容。
- 正则表达式
- 定义:
$(匹配字符串的结束位置):- 定义:
$表示匹配字符串的结束位置,通常用于确保字符串以特定字符或子字符串结尾。 - 示例:
- 正则表达式
a$:- 匹配任何以 "a" 结尾的字符串。
- 如输入 "banana":
a$匹配最后的 "a"。 - 如输入 "bananas":
a$不匹配任何内容(因为 "bananas" 不是以 "a" 结尾)。
- 正则表达式
\d{4}$:- 匹配以四位数字结尾的字符串。
- 如输入 "Year2024":
\d{4}$匹配 "2024"。 - 如输入 "ID20245":
\d{4}$不匹配任何内容(因为 "ID20245" 的最后四位不是单独的数字)。
- 正则表达式
- 定义:
\b(匹配单词边界):- 定义:
\b表示单词的边界,即字符的前后位置中,一个是字母数字字符([A-Za-z0-9_]),另一个不是。它常用于确保匹配的内容是完整的单词,而不是单词的一部分。 - 示例:
- 正则表达式
\bword\b:- 匹配完整的单词 "word"。
- 如输入 "word":
\bword\b匹配整个字符串 "word"。 - 如输入 "wordplay":
\bword\b不匹配(因为 "word" 是 "wordplay" 的一部分)。 - 如输入 "word, play":
\bword\b匹配 "word"(因为逗号是非字母字符)。
- 正则表达式
\bcat\b:- 匹配单独的单词 "cat"。
- 如输入 "a black cat":
\bcat\b匹配 "cat"。 - 如输入 "caterpillar":
\bcat\b不匹配(因为 "cat" 是 "caterpillar" 的一部分)。
- 正则表达式
- 定义:
\B(匹配非单词边界):- 定义:
\B表示非单词边界,即字符的前后位置中,两个都是字母数字字符或两个都不是。它用于确保匹配的内容在单词内部,或在非单词字符的中间。 - 示例:
- 正则表达式
\Bcat\B:- 匹配单词内部的 "cat"。
- 如输入 "scattering":
\Bcat\B匹配 "cat" 部分。 - 如输入 "cat":
\Bcat\B不匹配(因为 "cat" 是完整的单词,没有被其他字符包围)。
- 正则表达式
\Bing:- 匹配任何在单词内部的 "ing"。
- 如输入 "singing":
\Bing匹配 "ing" 部分(在单词内部)。 - 如输入 "ring":
\Bing不匹配(因为 "ing" 是单词结尾部分)。
- 正则表达式
- 定义:
^:用于匹配字符串的开头位置,确保匹配在字符串的最前面。$:用于匹配字符串的结尾位置,确保匹配在字符串的最后面。\b:用于匹配单词的边界,确保匹配的内容是独立的单词或部分。\B:用于匹配非单词边界,确保匹配的内容在单词内部或非单词字符的中间。
七、使用子表达式
子表达式是正则表达式中一个非常强大的工具,通过将表达式的某一部分括起来,可以对它们进行特殊的处理和操作。这使得正则表达式更加灵活和强大,能够实现复杂的匹配需求。
1. 括号
():定义子表达式
- 定义:括号
()用于将正则表达式的一部分括起来,使其成为一个整体,这部分表达式就称为一个子表达式。 - 作用:
- 分组:将多个字符或表达式作为一个整体对待,以便应用量词、位置匹配或其他操作。
- 捕获:默认情况下,子表达式会捕获匹配的内容,并将其存储在一个临时的缓存区中,可以在后续操作中引用这些匹配的内容。
- 重用:可以在表达式中后续引用之前的捕获组。
- 示例:
- 正则表达式
(abc)+:- 匹配字符串 "abc" 的一次或多次重复出现。
- 如输入 "abcabc":
(abc)+匹配整个字符串 "abcabc"。 - 如输入 "abcabcabc":
(abc)+匹配整个字符串 "abcabcabc"。
- 正则表达式
(ab|cd)+ef:- 匹配 "ab" 或 "cd" 这两个子串的一次或多次重复出现,并且最后匹配 "ef"。
- 如输入 "abef":匹配 "abef"。
- 如输入 "cdabef":匹配 "cdabef"。
- 如输入 "abcdcdef":匹配 "abcdcdef"。
- 正则表达式
2. 非捕获组
(?:...):定义子表达式但不捕获结果
- 定义:非捕获组
(?:...)也是一种括号语法,用于将表达式的一部分括起来,但与普通括号不同,它不会捕获匹配的内容,不会影响后续捕获组的编号。这种分组在不需要保存匹配结果时非常有用。 - 作用:
- 优化性能:由于不保存匹配结果,因此非捕获组的性能可能会比捕获组略好。
- 避免编号冲突:在复杂的正则表达式中,使用非捕获组可以避免不必要的捕获,保持捕获组的编号一致性。
- 示例:
- 正则表达式
(?:abc)+:- 匹配字符串 "abc" 的一次或多次重复出现,但不保存匹配结果。
- 如输入 "abcabc":
(?:abc)+匹配整个字符串 "abcabc",但不会将 "abc" 保存为一个捕获组。
- 正则表达式
(?:ab|cd)+ef:- 匹配 "ab" 或 "cd" 这两个子串的一次或多次重复出现,并且最后匹配 "ef",但不会捕获 "ab" 或 "cd"。
- 如输入 "abef":匹配 "abef"。
- 如输入 "cdabef":匹配 "cdabef"。
- 正则表达式
子表达式的捕获和引用
- 捕获组的引用:在正则表达式内部,可以通过
\1,\2,\3等方式来引用之前捕获的组。这在进行复杂匹配或替换时非常有用。- 示例:
- 正则表达式
(\d{3})-(\d{2})-(\d{4}):- 匹配形如 "123-45-6789" 的数字格式,并捕获每一部分。
\1引用第一个捕获组,即前三位数字 "123"。\2引用第二个捕获组,即中间两位数字 "45"。\3引用第三个捕获组,即最后四位数字 "6789"。
- 正则表达式
- 示例:
- 替换中的捕获组:在字符串替换操作中,可以使用捕获组来调整或重新排列匹配的内容。
- 示例:
- 使用正则表达式
(\w+)\s(\w+)替换"first last"为"last, first":- 捕获第一个单词
(\w+),然后捕获第二个单词(\w+)。 - 替换字符串可以是
"\2, \1",将名字和姓氏对调。
- 捕获第一个单词
- 使用正则表达式
- 示例:
():定义捕获组,允许分组和捕获匹配的子表达式内容,用于更复杂的匹配和替换。(?:...):定义非捕获组,用于分组但不捕获匹配结果,适用于不需要保存匹配内容的场景。- 捕获组的引用:可以通过
\1,\2等在表达式内部引用已捕获的内容,或在替换操作中使用捕获组来调整文本。
八、回溯引用
回溯引用(backreference)是一种强大的正则表达式功能,允许在同一个表达式中引用之前捕获的子表达式的匹配内容。这在处理重复的结构或需要保持一致性的匹配时非常有用。
1. 回溯引用的基本概念
- 定义:回溯引用是指在正则表达式中,通过特定的符号
\1,\2,\3等,引用在表达式中之前定义和捕获的子表达式。 - 用途:回溯引用常用于匹配重复出现的内容,或在需要对相同模式进行一致性检查时使用。
2. 使用方法
- 基本语法:
(\text{pattern})\1表示匹配一个模式并再次匹配相同的模式。(\d):表示一个数字,并将其捕获为第一个子表达式。\1:引用第一个子表达式,要求匹配的字符与之前捕获的内容一致。
- 多个回溯引用:如果有多个子表达式捕获组,可以使用
\2,\3等引用它们。(\d)(\w)\2\1:(\d)捕获一个数字并存储为\1。(\w)捕获一个字母并存储为\2。\2\1要求匹配捕获的字母和数字的重复顺序。
3. 回溯引用的实际应用
- 匹配重复字符:
- 示例:正则表达式
(\d)\1匹配两个连续的相同数字。- 如输入 "00":匹配 "00"。
- 如输入 "112233":可以匹配 "11", "22", "33"。
- 解释:
(\d)捕获一个数字并存储为第一个子表达式,\1要求第二个匹配的字符必须与第一个相同。
- 示例:正则表达式
- 匹配重复的字母组合:
- 示例:正则表达式
(\w\w)\1匹配两个相同的字母组合。- 如输入 "abab":匹配 "abab"。
- 如输入 "xyxy":匹配 "xyxy"。
- 解释:
(\w\w)捕获两个字母并存储为第一个子表达式,\1要求匹配的下两个字符与之前捕获的内容一致。
- 示例:正则表达式
- 匹配回文:
- 示例:正则表达式
(\w)(\w)\2\1匹配一个四个字母的回文结构,如 "abba"。- 如输入 "abba":匹配 "abba"。
- 如输入 "xyyx":匹配 "xyyx"。
- 解释:
(\w)捕获第一个和第二个字母分别为\1和\2,接着\2\1匹配前两个字母的逆序。
- 示例:正则表达式
4. 特殊场景中的回溯引用
- 替换中的回溯引用:在替换操作中,回溯引用可以用来重新排列或调整匹配内容。
- 示例:使用正则表达式
(\w+)\s(\w+)替换"first last"为"last, first":- 捕获第一个单词
(\w+),并将其存储为\1。 - 捕获第二个单词
(\w+),并将其存储为\2。 - 替换表达式使用
"\2, \1",将名字和姓氏对调。
- 捕获第一个单词
- 示例:使用正则表达式
- 嵌套回溯引用:在复杂表达式中,回溯引用可以嵌套使用,匹配更多层次的内容。
- 示例:正则表达式
((\d)\d)\2匹配特定的嵌套结构。- 解释:
(\d)捕获一个数字,(\d)\d捕获两个数字并作为一个整体引用,\2匹配第一个数字。
- 解释:
- 示例:正则表达式
- 回溯引用
\1,\2等允许在正则表达式中引用之前捕获的内容。- 回溯引用可以用来匹配重复的字符、字母组合,或检查相同模式的一致性。
- 回溯引用在替换操作中也非常有用,可以重新排列或调整匹配的内容。
- 在复杂表达式中,回溯引用可以嵌套使用,实现更加高级的匹配需求。
九、前后查找
前后查找(lookahead 和 lookbehind)是一种高级正则表达式技术,用于在不消耗字符的情况下,检查某个匹配是否满足特定条件。这意味着前后查找本身并不会返回匹配的字符,而是作为一种限制条件来约束其他匹配。
1. 前瞻(Lookahead)
前瞻用于判断一个字符串是否在某个特定的内容之前出现,但这个内容不会包含在最终的匹配结果中。
语法:
(?=...)解释:
(?=...)中的...是一个子表达式,表示如果当前位置满足...的条件,那么匹配成功,但实际的匹配结果不包括...。示例:
- 正则表达式:
\d(?=px)- 作用:匹配紧跟在 "px" 前的数字。
- 匹配字符串:"20px"
- 匹配结果:
20中的2,因为它后面跟着 "px"。
- 正则表达式:
应用场景:
- 例如在样式表中,你可能想匹配所有以 "px" 为单位的数字:
- 输入:"margin: 10px; padding: 5px; font-size: 12pt;"
- 匹配正则:
\d+(?=px) - 结果:
10和5,因为它们后面都跟着 "px"。
- 例如在样式表中,你可能想匹配所有以 "px" 为单位的数字:
2. 后顾(Lookbehind)
后顾用于判断一个字符串是否在某个特定的内容之后出现,并且这个内容不会包含在最终的匹配结果中。
语法:
(?<=...)解释:
(?<=...)中的...是一个子表达式,表示如果当前位置之前的字符串满足...的条件,那么匹配成功,但实际的匹配结果不包括...。示例:
- 正则表达式:
(?<=\$)\d+- 作用:匹配紧跟在美元符号
$后的数字。 - 匹配字符串:"总计: $100"
- 匹配结果:
100,因为它前面有$符号。
- 作用:匹配紧跟在美元符号
- 正则表达式:
应用场景:
- 例如在财务数据中,你可能想提取所有以美元表示的数值:
- 输入:"价格:$50, $100, ¥200"
- 匹配正则:
(?<=\$)\d+ - 结果:
50和100,因为它们前面都跟着 "$" 符号。
- 例如在财务数据中,你可能想提取所有以美元表示的数值:
3. 负前瞻(Negative Lookahead)
负前瞻用于判断某个字符串是否不在某个特定内容之前出现,且这个内容不会包含在最终的匹配结果中。
语法:
(?!...)解释:
(?!...)中的...是一个子表达式,表示如果当前位置满足...的条件,则匹配失败,只有不满足...的情况下,匹配才成功。示例:
- 正则表达式:
\d(?!px)- 作用:匹配后面不跟 "px" 的数字。
- 匹配字符串:"20pt 30px"
- 匹配结果:
2和0,因为它们后面不跟 "px"。
- 正则表达式:
应用场景:
- 例如在文本中,过滤掉特定单位的数值,如排除以 "px" 为单位的数字:
- 输入:"margin: 20px; padding: 10pt; font-size: 15px;"
- 匹配正则:
\d+(?!px) - 结果:
10,因为它后面没有 "px"。
- 例如在文本中,过滤掉特定单位的数值,如排除以 "px" 为单位的数字:
4. 负后顾(Negative Lookbehind)
负后顾用于判断某个字符串是否不在某个特定内容之后出现,且这个内容不会包含在最终的匹配结果中。
语法:
(?<!...)解释:
(?<!...)中的...是一个子表达式,表示如果当前位置之前的字符串满足...的条件,则匹配失败,只有不满足...的情况下,匹配才成功。示例:
- 正则表达式:
(?<!\$)\d+- 作用:匹配前面不跟
$的数字。 - 匹配字符串:"总计: 100 元, $200 美元"
- 匹配结果:
100,因为它前面没有$符号。
- 作用:匹配前面不跟
- 正则表达式:
应用场景:
- 例如在文本中,排除特定货币符号的数值:
- 输入:"$100, 200元, $300"
- 匹配正则:
(?<!\$)\d+ - 结果:
200,因为它前面没有 "$"。
- 例如在文本中,排除特定货币符号的数值:
- 前瞻
(?=...)和 后顾(?<=...)用于在不包含条件本身的情况下,对字符串进行条件约束匹配。- 负前瞻
(?!...)和 负后顾(?<!...)则用于排除特定条件,使得匹配更加灵活。- 前后查找的强大之处在于它们不消耗字符,因此能够与其他正则表达式结合使用,实现复杂的匹配需求。
十、嵌入条件
正则表达式中的嵌入条件(conditional expressions)允许根据前面的匹配结果选择不同的匹配路径。这使得正则表达式能够处理更复杂的匹配场景,类似于编程中的条件语句。
1. 条件表达式的语法
- 语法:
(?ifthen|else)if:表示一个条件子表达式。如果这个子表达式成功匹配,选择then部分。then:如果if部分成功,匹配这个部分。else:如果if部分失败,则匹配这个部分(else是可选的)。
2. 使用条件表达式的示例
- 基本示例:
- 正则表达式:
(?:(\d)\d{2}|(\w)\w{2})- 解释:这里的正则表达式表示,如果第一个捕获组(
\d)成功匹配,后面必须是两个数字(\d{2})。否则,匹配第二个捕获组(\w)后面跟两个字母(\w{2})。 - 输入:"12ab"
- 匹配结果:
12匹配第一个部分;ab匹配第二个部分。
- 匹配结果:
- 解释:这里的正则表达式表示,如果第一个捕获组(
- 正则表达式:
- 复杂示例:
- 正则表达式:
(?:(\d{3})|(\w{2}))(?(1)\d{2}|\w{2})- 解释:如果第一个捕获组(
(\d{3}))成功匹配三个数字,那么匹配后面两个数字(\d{2})。如果第一个捕获组没有匹配(即匹配两个字母(\w{2})),则匹配后面两个字母(\w{2})。 - 输入:"12345"
- 匹配结果:
123匹配第一个部分;45匹配第二个部分。
- 匹配结果:
- 输入:"abxy"
- 匹配结果:
ab匹配第一个部分;xy匹配第二个部分。
- 匹配结果:
- 解释:如果第一个捕获组(
- 正则表达式:
3. 应用场景
- 验证特定格式的输入:
- 在需要验证用户输入的格式时,条件表达式可以根据特定条件选择不同的验证规则。例如,验证电话号码或身份证号码的格式,可能根据国家或区域不同而有所变化。
- 处理可变格式的数据:
- 当数据格式可变时,例如日志文件中可能包含不同类型的记录,条件表达式可以根据记录类型选择不同的解析方式。
- 复杂文本处理:
- 在文本处理任务中,特别是那些涉及到多种格式的文本,条件表达式可以根据先前的匹配结果选择适当的后续匹配路径,从而进行更复杂的文本提取。
4. 正则表达式的实际例子
- 例子
1:匹配一个可能是数字或字母,并且其后的部分是固定格式。
- 正则表达式:
(?:(\d)\d{2}|(\w)\w{2})(?(1)\d{2}|\w{2})- 解释:如果第一个捕获组匹配数字,那么后面必须是两个数字;如果第一个捕获组匹配字母,那么后面必须是两个字母。
- 输入:"12345" 匹配成功,
123和45分别对应数字和两个数字。 - 输入:"abxy" 匹配成功,
ab和xy分别对应字母和两个字母。
- 正则表达式:
- 例子
2:匹配一个字符串,前缀是数字或字母,并且根据前缀的不同,后缀的规则也不同。
- 正则表达式:
(?:(\d{2,3})|(\w{1,2}))(?(1)\d{3,4}|\w{3,4})- 解释:如果前面匹配了两个或三个数字,则后面匹配三个或四个数字;如果前面匹配了一个或两个字母,则后面匹配三个或四个字母。
- 输入:"1234567" 匹配成功,
123和4567分别对应两个数字和三个数字。 - 输入:"abxyz" 匹配成功,
ab和xyz分别对应字母和三个字母。
- 正则表达式:
- 条件表达式
(?ifthen|else)使得正则表达式能够根据条件选择不同的匹配路径。- 使用场景:验证格式、处理可变格式的数据、复杂文本处理等。
- 实例:可以处理不同格式的数据,根据先前的匹配结果决定后续匹配的内容。





