正则表达式中的正向预查和负向预查是一种特殊的匹配模式,它允许我们在匹配时考虑字符出现的前后环境。正向预查和负向预查是通过特殊的语法符号来定义的,分别为正向预查符号(?=\)和负向预查符号(?!\)。

1. 正向预查
正向预查是指在匹配过程中,只匹配满足指定条件的字符串,并不占用实际的匹配结果。它使用正向预查符号(?=\)进行定义。例如,如果我们希望匹配一个字符串中后面紧跟着数字的字符,但并不想匹配这个数字本身,可以使用正向预查。代码示例如下:

import re

text = "apple123orange"
pattern = r"\w+(?=\d)"

result = re.findall(pattern, text)
print(result)  # 输出结果为 ['apple']

上述示例中,正则表达式r"\w+(?=\d)"中的正向预查符号(?=\)表示后面必须紧跟一个数字,但并不匹配这个数字。因此,只有满足这个条件的"apple"被匹配到,而不是整个"apple123"。

2. 负向预查
负向预查是指在匹配过程中,只匹配满足指定条件的字符串,并不占用实际的匹配结果。它使用负向预查符号(?!\)进行定义。例如,如果我们希望匹配一个字符串中后面不紧跟着数字的字符,可以使用负向预查。代码示例如下:

import re

text = "orange123apple"
pattern = r"\w+(?!\d)"

result = re.findall(pattern, text)
print(result)  # 输出结果为 ['orange']

上述示例中,正则表达式r"\w+(?!\d)"中的负向预查符号(?!\)表示后面不能紧跟一个数字。因此,只有满足这个条件的"orange"被匹配到,而不是整个"orange123"。

3. 正向预查的应用场景
正向预查的主要应用场景是需要在匹配时考虑特定字符出现的条件,但又不希望这些字符出现在实际匹配结果中。例如,在提取URL时,我们可以使用正向预查来匹配特定域名后面的路径,而不包括域名本身。代码示例如下:

import re

text = "https://www.example.com/path"
pattern = r"(?<=https://www.example.com/)\w+"

result = re.findall(pattern, text)
print(result)  # 输出结果为 ['path']

上述示例中,正则表达式r"(?<=https://www.example.com/)\w+"使用了正向预查符号(?<=\),表示前面必须是"https://www.example.com/",但并不匹配这个字符串。因此,只有满足这个条件的"path"被匹配到,而不是整个字符串。

4. 负向预查的应用场景
负向预查的主要应用场景是需要在匹配时排除特定字符出现的条件。例如,在匹配电话号码时,我们可以使用负向预查来排除一些特殊字符。代码示例如下:

import re

text = "Phone: 123-4567890"
pattern = r"\d+(?!\-)"

result = re.findall(pattern, text)
print(result)  # 输出结果为 ['123', '4567890']

上述示例中,正则表达式r"\d+(?!\-)"中的负向预查符号(?!-)表示后面不能紧跟一个"-"。因此,只有满足这个条件的数字被匹配到,"123"和"4567890"都被匹配到,而不是包括"-"的"123-4567890"。

正向预查和负向预查在正则表达式中起到了很重要的作用,可以灵活地处理复杂的匹配需求。但需要注意的是,正向预查和负向预查只是匹配条件,并不占用实际的匹配结果,因此在提取实际的匹配结果时需要额外的处理。