断言
(练习网站)[https://regexlearn.com/zh-cn/learn/regex101]
正向先行断言
在正则表达式中,(?=...)
是一个正向肯定预查(positive lookahead)的语法结构。它用于在匹配字符串时,查找某个位置后面是否跟着特定的模式,而不消耗实际的字符。
具体来说,(?=PM)
匹配一个数字序列(\d+
),但该数字序列后面必须紧跟着字符串 “PM”。这种预查会在匹配的时候向前看,并确定某个位置后面是否满足预期的条件。
举个例子,假设有以下文本:
12PM 3PM 6PM
如果使用正则表达式 \d+(?=PM)
进行匹配,它将匹配到以下结果:
- “12”:在 “12” 后面紧跟着 “PM”。
- “3”:在 “3” 后面紧跟着 “PM”。
- “6”:在 “6” 后面紧跟着 “PM”。
需要注意的是,正向肯定预查只是用来判断某个位置后面的模式是否匹配,它并不会包含在最终的匹配结果中。因此,预查部分(即 “PM”)不会包含在匹配的结果中,只有数字序列会被捕获。
import re
res = re.findall("\d+(?=PM)", "23PM 42ji")
print(res)
# ['23']
负向先行断言
负向先行断言(negative lookahead)是正则表达式的一种语法结构,用于在匹配字符串时,查找某个位置后面是否不跟着特定的模式。它与负向后行断言类似,但是用于否定条件。
负向先行断言的语法结构是 (?!...)
,其中 ...
表示要匹配的模式。
举个例子,假设我们想匹配一个字符串中不跟着 “xyz” 的数字序列。我们可以使用负向先行断言来实现这个目标。
正则表达式:\d+(?!xyz)
这个正则表达式会匹配一个或多个数字,但要求它后面不跟着 “xyz”。下面是一些例子来说明匹配情况:
- “123”:匹配成功,因为它后面不是 “xyz”。
- “456xyz”:不匹配,因为 “456” 后面是 “xyz”。
- “789abc”:匹配成功,因为 “789” 后面不是 “xyz”。
负向先行断言允许我们在匹配过程中限制某个位置后面的内容,以满足特定的条件。
import re
res = re.findall("\d+(?!PM)", "23PM 42ji")
print(res)
# ['2', '42']
负向后行断言
负向后行断言是正则表达式的一种语法结构,用于在匹配字符串时,查找某个位置前面是否不跟着特定的模式。它类似于正向肯定预查,但是用于否定条件。
假设我们想匹配一个字符串中不紧跟着 “abc” 的 “def”。我们可以使用负向后行断言来实现这个目标。
正则表达式:(?<!abc)def
这个正则表达式会匹配 “def”,但是要求它前面的三个字符不是 “abc”。下面是一些例子来说明匹配情况:
- “def”:匹配成功,因为它前面不是 “abc”。
- “abcdef”:不匹配,因为 “def” 前面是 “abc”。
- “xyzdef”:匹配成功,因为 “def” 前面不是 “abc”。
负向后行断言允许我们在匹配过程中限制某个位置前面的内容,以满足特定的条件。
import re
res = re.findall(r'(?<!abc)PM', "abcPM 23pm")
print(res)
# []
正向后行断言
正向后行断言(positive lookbehind)是正则表达式的一种语法结构,用于在匹配字符串时,查找某个位置之前是否跟着特定的模式。它类似于正向肯定预查,但是用于前面的条件。
正向后行断言的语法结构是 (?<=...)
,其中 ...
表示要匹配的模式。
举个例子,假设我们想匹配一个字符串中紧跟着 “abc” 的 “def”。我们可以使用正向后行断言来实现这个目标。
正则表达式:(?<=abc)def
这个正则表达式会匹配 “def”,但要求它前面的三个字符是 “abc”。下面是一些例子来说明匹配情况:
- “abcdef”:匹配成功,因为 “def” 前面是 “abc”。
- “xyzabcdef”:不匹配,因为 “def” 前面不是 “abc”。
- “abcxyzdef”:不匹配,因为 “def” 前面不是紧跟着 “abc”。
正向后行断言允许我们在匹配过程中限制某个位置之前的内容,以满足特定的条件。需要注意的是,断言部分(即 “abc”)不会包含在最终的匹配结果中,只有断言后面的部分会被捕获。
import re
res = re.findall("(?<=23)\w+", "23PM 42ji")
print(res)
匹配模式
贪婪匹配
正则默认贪婪匹配,意思就是匹配到第一个符合要求的以后,不会暂停,会继续匹配
懒惰匹配
匹配到第一个符合要求的就不匹配了,例如:
ber beer beeer beeeer
.*?r
只会匹配到ber,这第一个单词
与贪婪匹配不同,懒惰匹配在第一次匹配时停止。下面的例子中,在 * 之后添加 ?,将查找以 r 结尾且前面带有任意字符的第一个匹配项。这意味着本次匹配将会在第一个字母 r 处停止。
引用组
引用组(capturing group)是正则表达式中的一种语法结构,用于将匹配的内容进行分组并在后续操作中引用。引用组使用圆括号 ( )
来定义。
当正则表达式匹配到引用组时,匹配的内容会被捕获并保存
在一个特定的索引
中,可以在后续的正则表达式操作或替换中使用这些引用。
例如:
ha-ha,haa-haa
(ha)-\1,(haa)-\2
\1 保存的是ha,\2保存的是haa
下面是一个使用引用组的 Python 代码示例:
import re
# 定义要匹配的字符串
text = "Hello, my name is John Doe."
# 使用引用组进行匹配和替换
pattern = r"Hello, my name is ([A-Za-z\s]+)\."
replacement = r"Nice to meet you, \1!"
# 替换匹配的内容并输出结果
result = re.sub(pattern, replacement, text)
print(result)
运行以上代码,将输出:
Nice to meet you, John Doe!
下面是 re.sub 函数的完整参数列表和用法:
re.sub(pattern, repl, string, count=0, flags=0)
pattern:要匹配的正则表达式模式。
repl:替换字符串,可以是普通字符串或一个替换函数。
string:待处理的原始字符串。
count(可选):指定替换的最大次数,默认为 0,表示全部替换。
flags(可选):用于控制正则表达式的匹配方式,例如忽略大小写、多行匹配等。
在这个例子中,我们使用引用组 ( )
将 ([A-Za-z\s]+)
匹配的内容进行了分组。这个引用组匹配一个或多个字母和空格,表示一个人的姓名。然后,我们使用 \1
来引用第一个引用组的匹配结果,将其用于替换字符串中的内容:插入到"replacement"中\1处
。
在替换中,我们将匹配到的内容替换为 “Nice to meet you, “ 加上引用组中捕获的姓名。因此,”Hello, my name is John Doe.” 被替换为 “Nice to meet you, John Doe!”。
通过引用组,我们可以在正则表达式中捕获并引用特定的匹配结果,从而进行更灵活的操作和替换。