我的答案分为四个部分。
第一部分包含我对问题的解决方案。对其他内容不感兴趣的读者可以跳过其他部分。
其余三个部分关注的是识别前面有不同数字和后面有不同数字的相等数字对。三个部分中的第一个与它们匹配;另外两个将他们抓成一组。
我加入了最后一部分,因为我想与不熟悉它的人分享有史以来最伟大的正则表达式技巧,因为我觉得它非常酷、聪明,而且简单。它记录在here。请注意,为了制造悬念,该链接的作者在鼓声揭晓之前包含了一个冗长的序言。
判断一个字符串是否包含两个连续相等的数字,前面有一个不同的数字,后面有一个不同的数字
您可以按如下方式测试字符串:
import re
r = r'(\d)(?!\1)(\d)\2(?!\2)\d'
arr = ["123456678", "1123455a666788"]
for s in arr:
print(s, bool(re.search(r, s)) )
展示
123456678 True
1123455a666788 False
Run Python code | Start your engine!1
正则表达式引擎执行以下操作。
(\d) : match a digit and save to capture group 1 (preceding digit)
(?!\1) : next character cannot equal content of capture group 1
(\d) : match a digit in capture group 2 (first digit of pair)
\2 : match content of capture group 2 (second digit of pair)
(?!\2) : next character cannot equal content of capture group 2
\d : match a digit
(?!\1) 和 (?!\2) 是负前瞻。
使用 Python 的 regex 模块来匹配具有所需属性的连续数字对
您可以将以下正则表达式与 Python 的 regex 模块一起使用来获取匹配的数字对。
r'(\d)(?!\1)\K(\d)\2(?=\d)(?!\2)'
Regex Engine
正则表达式引擎执行以下操作。
(\d) : match a digit and save to capture group 1 (preceding digit)
(?!\1) : next character cannot equal content of capture group 1
\K : forget everything matched so far and reset start of match
(\d) : match a digit in capture group 2 (first digit of pair)
\2 : match content of capture group 2 (second digit of pair)
(?=\d) : next character must be a digit
(?!\2) : next character cannot equal content of capture group 2
(?=\d) 是一个正向预测。 (?=\d)(?!\2) 可以替换为 (?!\2|$|\D)。
将具有所需属性的连续数字对保存到捕获组中
另一种获取匹配数字对的方法,不需要regex模块,是从以下正则表达式的匹配中提取捕获组2的内容。
r'(\d)(?!\1)((\d)\3)(?!\3)(?=\d)'
Re engine
执行以下操作。
(\d) : match a digit in capture group 1
(?!\1) : next character does not equal last character
( : begin capture group 2
(\d) : match a digit in capture group 3
\3 : match the content of capture group 3
) : end capture group 2
(?!\3) : next character does not equal last character
(?=\d) : next character is a digit
使用 有史以来最伟大的正则表达式技巧来识别具有所需属性的连续数字对
我们使用下面的正则表达式来匹配字符串。
r'(\d)(?=\1)|\d(?=(\d)(?!\2))|\d(?=\d(\d)\3)|\d(?=(\d{2})\d)'
当有匹配时,我们不注意匹配的是哪个字符,而是检查捕获组 4 ((\d{2})) 的内容,如下所述。
The Trick in action
交替的前三个组成部分对应于四位数字的字符串不能具有第二个和第三个数字相等,第一个和第二个不相等,第三个和第四个相等的属性的方式。它们是:
(\d)(?=\1) : assert first and second digits are equal
\d(?=(\d)(?!\2)) : assert second and third digits are not equal
\d(?=\d(\d)\3) : assert third and fourth digits are equal
因此,如果有一个数字匹配并且交替的前三个部分失败,则最后一部分 (\d(?=(\d{2})\d)) 必须成功,并且它包含的捕获组 (#4) 必须包含两个相等的数字具有所需的属性。 (需要最后的\d 来断言感兴趣的数字对后面跟着一个数字。)
如果有匹配,我们如何确定交替的最后一部分是否是匹配的?
当这个正则表达式匹配一个数字时,我们对那个数字不感兴趣。相反,我们希望捕获第 4 组 ((\d{2}))。如果该组为空,我们得出结论,交替的前三个组成部分之一与数字匹配,这意味着匹配数字后面的两个数字不具有它们相等且不等于它们之前和之后的数字的属性.
但是,如果捕获组 4 不为空,则表示交替的前三个部分中没有一个与数字匹配,因此交替的最后一部分必须匹配并且匹配数字后面的两个数字,这被保存在捕获组 4 中,具有所需的属性。
1.移动光标查看详细说明。